svelte-on-rails 5.1.0 → 5.2.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: 0e2782073f696f72736004ae21d57a71e4429fb878f915954e36628e16904de9
4
- data.tar.gz: 2d041a60e7908ce20ab64f490ccebe3d3c673882986c83a64981aaf1e9931768
3
+ metadata.gz: 6f7ba72715095d212a289e5fba57a8ddd78b358474e4219a5b3c47f3b7d66c88
4
+ data.tar.gz: e690deefa5507a42cf31176efc368c3ff2f304ce1ff057dc79f431e33b5c4232
5
5
  SHA512:
6
- metadata.gz: 5d1fef990a79dfa782b0101f33ed64f3631d126ea6ef16dfde8d21d240653d8d938a87689955af288b862362216fbb760db61e79d709c512b242d0f86ad823d1
7
- data.tar.gz: 430b9cf7ab45fb7e0ab629b4de95bd262e8b02bd68a58793dcd614832dfd2bb04d63f52d20ddc6639dc951d8ae132188dee755dadab1042f98a0268dcf4bab63
6
+ metadata.gz: c1b2150fa517ce388feaf13c9816b8d71cb339c9ac9670d7552096430a8cddff8688629ca96c58dbcde715e4f9e9b3953e6760ab6e67c37f3a0ad10797b8fcc9
7
+ data.tar.gz: 275691b15976c8dbcd551b3c07ec7495da686c7fa23192b5aca471527b4fe63c20fa8048851a3d9b0085756de52bc7ae1d1e4e5a663114a9fbed9608873ba68e
data/README.md CHANGED
@@ -365,7 +365,17 @@ turbo_stream:
365
365
  channel: 'public'
366
366
  ```
367
367
 
368
- ## ActionCable!
368
+ ## ActionCable vs TurboStream
369
+
370
+ - **ActionCable**
371
+ - Cleaner setup no html needed
372
+ - Seams to initialize securer, especially for testings (not: production)
373
+ - **TurboStream**
374
+ - Secured Streams by html-tag `signed-stream-name` if you want to send confidential data
375
+ over streams or have different channels for each user privileges
376
+ - Has [Compatibility issue with UJS](https://github.com/hotwired/turbo-rails?tab=readme-ov-file#compatibility-with-rails-ujs)
377
+
378
+ ## SvelteOnRails::ActionCable.send
369
379
 
370
380
  ActionCable is the more basic library behind `TurboStream` and it is a second Option to call Javascript Actions from the server.
371
381
 
@@ -395,7 +405,8 @@ Add to `application.js`
395
405
 
396
406
  ```javascript
397
407
  import { createConsumer } from "@rails/actioncable"
398
- import {dispatchSvelteStreamEvent, actionCableDebugLog} from '@csedl/svelte-on-rails'
408
+ import { SvelteOnRails, dispatchSvelteStreamEvent, actionCableDebugLog } from '@csedl/svelte-on-rails'
409
+ SvelteOnRails.debug = true
399
410
 
400
411
  const consumer = createConsumer()
401
412
 
@@ -413,9 +424,7 @@ consumer.subscriptions.create("SvelteOnRailsChannel", {
413
424
  })
414
425
  ```
415
426
 
416
- By setting `debug = true` [node package](https://www.npmjs.com/package/@csedl/svelte-on-rails) you see what it is doing.
417
-
418
- **WhatdispatchSvelteStreamEvent does**
427
+ **What dispatchSvelteStreamEvent does**
419
428
 
420
429
  - Without the attribute `component` given,
421
430
  it searches for all elements with the class `svelte-component` and fires the event `channel-action`
@@ -424,18 +433,40 @@ By setting `debug = true` [node package](https://www.npmjs.com/package/@csedl/sv
424
433
 
425
434
  **Usage**
426
435
 
436
+ `app/frontend/javascript/components/folder/MyComponent.svelte`
437
+
438
+ ```sveltehtml
439
+ <script>
440
+ import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
441
+
442
+ function handleCableEvent(event) {
443
+ console.log('Event received by Turbo Stream', event.detail)
444
+ }
445
+ </script>
446
+ <!--on ANY element:-->
447
+ <h1 use:addComponentStreamListener={handleCableEvent}>Test TurboStreams Channel</h1>
448
+ ```
449
+
450
+ The `addComponentStreamListener` adds the eventListener `stream-action` on the wrapping Element.
451
+ The «wrapping Element» is the Element from the view helper `svelte_component` with the class `svelte-component`.
452
+
427
453
  Now you can dispatch events on the component by:
428
454
 
429
455
  ```ruby
430
- ActionCable.server.broadcast("svelte_on_rails_channel",
431
- {
432
- eventDetail: { message: "Sent by ActionCable: äöü🤣🌴🌍漢字" },
433
- component: '/javascript/components/ReceiveFromChannel',
434
- }
456
+ SvelteOnRails::ActionCable.send(
457
+ 'folder/MyComponent',
458
+ { message: "greetings from Server: äöü🤣🌴🌍漢字" }
435
459
  )
436
460
  ```
437
461
 
438
- # Turbo::StreamsChannel.send!
462
+ And you will find the object, with the message key on the browser logs.
463
+
464
+ Without any arguments, just by `SvelteOnRails::ActionCable.send` it would fire the `stream-action` event on all components.
465
+
466
+ # SvelteOnRails::TurboStream.send
467
+
468
+ Turbo Stream makes more sense when you think of sending confidential data to the components
469
+ or you want to separate to channels based on user groups, for example.
439
470
 
440
471
  Few setup is needed for that:
441
472
 
@@ -449,15 +480,15 @@ rails turbo:install
449
480
  ```
450
481
 
451
482
  make sure that `import "@hotwired/turbo-rails"` is on your application.js and set the view helper
452
- `<%= turbo_stream_from 'public' %>` to your view.
483
+ `<%= turbo_stream_from 'authenticated' if current_user %>` to your view.
453
484
 
454
- If a channel (e.g.: `public`) is active and you have an HTML element with a HTML-ID (e.g.: `svelte-on-rails-stream-actions-box`),
485
+ If a channel (e.g.: `authenticated`) is active and you have an HTML element with a HTML-ID (e.g.: `svelte-on-rails-stream-actions-box`),
455
486
  you can test it by:
456
487
 
457
488
  ```ruby
458
489
  Turbo::StreamsChannel.send(
459
490
  "broadcast_append_to",
460
- 'public',
491
+ 'authenticated',
461
492
  target: 'svelte-on-rails-stream-actions-box',
462
493
  content: "<div>Turbo-Streams are working!</div>"
463
494
  )
@@ -467,27 +498,13 @@ When this works you are good to go.
467
498
 
468
499
  **Minimal Usage Example**
469
500
 
470
- ```sveltehtml
471
- <script>
472
- import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
473
-
474
- function handleCableEvent() {
475
- console.log('Event received by Turbo Stream')
476
- }
477
- </script>
478
- <!--on any element:-->
479
- <h1 use:addComponentStreamListener={handleCableEvent}>Test TurboStreams Channel</h1>
480
- ```
481
-
482
501
  And call this by:
483
502
 
484
503
  ```ruby
485
- SvelteOnRails::TurboStream.new.dispatch_event
504
+ SvelteOnRails::TurboStream.send
486
505
  ```
487
506
  **What it does**
488
507
 
489
- - The `addComponentStreamListener` adds the eventListener `stream-action` on the wrapping Element
490
- - The «wrapping Element» is the Element from the view helper `svelte_component` with the class `svelte-component`.
491
508
  - A Stimulus controller is pushed to all subscribers of the configured channel.
492
509
  - You can override the channel name by passing `channel` to the method.
493
510
 
@@ -519,8 +536,6 @@ Then, call it by:
519
536
  )
520
537
  ```
521
538
 
522
-
523
-
524
539
  ## More rake tasks
525
540
 
526
541
  This tasks are more for testing/playground purposes
@@ -575,30 +590,12 @@ This will cause the installer, to install the npm package from a local path inst
575
590
  Then run the tests and start contributing.
576
591
 
577
592
  **RUN THE FIRST TEST (!)**: Testing is complex here because of the design based on the installer test.
578
- On Problems, i always run the `Installer > destroy and create rails app > FIRST TEST > [...] check if javascript works`. When this passes,
579
- all the others passing mostly.
580
-
581
- Tests are based on the included templates, like the `hello world template` and on the installer.
582
-
583
- Here I learned how to write tests! Testing installers is heavy, you will read about it in the
584
- test_helpers. But I have done my best to give all the code a clear structure.
585
- I hope you like it, and improvements are welcome.
586
-
587
- **Installer tests** starting with completely destroy the rails app within the `generated_test_app_path`,
588
- generating a new rails app and running the installer and test by `playwright` if the components are working.
589
-
590
- **component tests** only checking if a rails server is alive, and if not, install and run a rails app.
591
- For this is the testing helper `start_rails_server_unless_ping`. This step may only be slow on the
592
- first run, then it is fast. And on every repeating the test it always overwrites the components
593
- with the components from the template by the testing helper `install_hello_world(
594
- ['rails_vite_hello_world'],
595
- app_root: generated_rails_app_root,
596
- force: true,
597
- silent: true
598
- )`. At the end of the test it leaves the rails server running.
599
-
600
- On that way a developer can just edit the templates and run a test and see always the refreshed
601
- content on the browser and on the app within the `generated_test_app_path`.
593
+ On Problems, i always run the `Installer > destroy and create rails app > FIRST TEST > [...] check if javascript works`.
594
+ If there are problems, open the generated app on a IDE and check errors there.
595
+
596
+ When this passes, all the others passing mostly.
597
+
598
+ At the end of the most tests it leaves the rails server running, so that you can see the result on `localhost:3000`.
602
599
 
603
600
  NOTE: Theese tests are dependend on your environment, including the running ruby version!
604
601
  I am working on rvm. If you work on a different environment, some (not many) changes may be necessary.
@@ -133,6 +133,10 @@ module SvelteOnRails
133
133
  utils_i.add_route(" get \"svelte_on_rails_hello_world/turbo_stream_action\"", app_root: Rails.root)
134
134
  npm_i = SvelteOnRails::Installer::Npm
135
135
  npm_i.install_or_update_package('axios')
136
+ npm_i.install_or_update_package('@rails/actioncable')
137
+ js_i = SvelteOnRails::Installer::Javascript
138
+ init_stat = '../initializers/actionCable.js'
139
+ js_i.append_import_statement(application_js_path, init_stat, "import '#{init_stat}';")
136
140
  @hello_world_path = hw_i.install_hello_world(['rails_vite_hello_world'], app_root: nil, force: true, silent: true)
137
141
  end
138
142
 
@@ -1,6 +1,11 @@
1
1
  module SvelteOnRails
2
2
  class ActionCable
3
- def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, channel: "svelte_on_rails_channel")
3
+ def self.send(component = nil, event_detail = nil, event: 'stream-action', selector: nil, channel: nil)
4
+
5
+ _channel = configs['channel'] || channel
6
+ unless _channel.present?
7
+ raise 'Missing attribute or configuration: action_cable/channel'
8
+ end
4
9
 
5
10
  if event != 'stream-action' && !selector
6
11
  raise "Another event name than the default one is only possible together with a selector"
@@ -13,30 +18,19 @@ module SvelteOnRails
13
18
  selector: selector
14
19
  }
15
20
 
16
- #args_enc = Base64.strict_encode64(args.to_json)
21
+ ::ActionCable.server.broadcast(
22
+ _channel,
23
+ args
24
+ )
17
25
 
18
- ActionCable.server.broadcast(channel, args)
19
26
 
20
27
  end
21
28
 
22
29
  private
23
30
 
24
- def configs
25
- @configs ||= begin
26
-
27
- conf = SvelteOnRails::Configuration.instance
28
- unless conf.configs[:turbo_stream]
29
- raise '[svelte-on-rails] missing configuration: :turbo_stream'
30
- end
31
- unless conf.configs[:turbo_stream]['target_html_id']
32
- raise '[svelte-on-rails] missing configuration: turbo_stream/target_html_id'
33
- end
34
- unless conf.configs[:turbo_stream]['channel']
35
- raise '[svelte-on-rails] missing configuration: turbo_stream/channel'
36
- end
37
-
38
- conf.configs[:turbo_stream]
39
- end
31
+ def self.configs
32
+ SvelteOnRails::Configuration.instance.configs[:action_cable]
40
33
  end
34
+
41
35
  end
42
36
  end
@@ -1,6 +1,6 @@
1
1
  module SvelteOnRails
2
2
  class TurboStream
3
- def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, channel: nil)
3
+ def self.send(component = nil, event_detail = nil, event: 'stream-action', selector: nil, channel: nil)
4
4
 
5
5
  if event != 'stream-action' && !selector
6
6
  raise "Another event name than the default one is only possible together with a selector"
@@ -26,7 +26,7 @@ module SvelteOnRails
26
26
 
27
27
  private
28
28
 
29
- def configs
29
+ def self.configs
30
30
  @configs ||= begin
31
31
 
32
32
  conf = SvelteOnRails::Configuration.instance
@@ -27,6 +27,10 @@ turbo_stream:
27
27
  # html-id of any element that must exist for being able to receive actions (turbo streams can only work this way)
28
28
  channel: 'public'
29
29
 
30
+ action_cable:
31
+ # if you want to use it
32
+ channel: "svelte_on_rails_channel"
33
+
30
34
  development:
31
35
  watch_changes: true
32
36
  # Check on every request if any file within the svelte components folder have changed, for recompiling
@@ -5,29 +5,39 @@ class SvelteOnRailsHelloWorldController < ApplicationController
5
5
 
6
6
  def turbo_stream_action
7
7
 
8
- if params['increase']
9
- SvelteOnRails::TurboStream.new.dispatch_event(
10
- event: 'click',
11
- selector: '.counter-button',
12
- component: '/javascript/components/ReceiveFromChannel'
8
+ comp = '/javascript/components/ReceiveFromChannel'
9
+
10
+ case params['stream']
11
+
12
+ when 'action-cable-to-component'
13
+ SvelteOnRails::ActionCable.send(
14
+ comp,
15
+ { message: "#{SecureRandom.hex(2)} Sent by <span class='transfer'>ActionCable</span>: äöü🤣🌴🌍漢字", class: 'action-cable-to-component' },
16
+ event: 'stream-action'
13
17
  )
14
- render plain: 'increase-action streamed'
15
- elsif params['action_cable']
16
-
17
- ActionCable.server.broadcast("svelte_on_rails_channel",
18
- {
19
- eventDetail: { message: "Sent by ActionCable: äöü🤣🌴🌍漢字" },
20
- component: '/javascript/components/ReceiveFromChannel',
21
- }
18
+
19
+ when 'action-cable-to-element'
20
+ SvelteOnRails::ActionCable.send(
21
+ comp,
22
+ { message: "#{SecureRandom.hex(2)} <span class='transfer'>ActionCable to .my-custom-class / my-custom-event</span>", class: 'action-cable-to-element' },
23
+ selector: '.my-custom-class',
24
+ event: 'my-custom-event'
22
25
  )
23
- #SvelteOnRails::ActionCable.new.dispatch_event(channel: "svelte_on_rails_channel", event_detail: { message: "Hello from SvelteChannel!" })
24
26
 
25
- render plain: 'ActionCable streaming'
26
- else
27
- SvelteOnRails::TurboStream.new.dispatch_event(
28
- event_detail: { message: "Sent by TurboStream: äöü🤣🌴🌍漢字", user: "Müller" }
27
+ when 'turbo-stream-to-all-components'
28
+ SvelteOnRails::TurboStream.send(
29
+ nil,
30
+ { message: "Sent by TurboStream: äöü🤣🌴🌍漢字", class: 'turbo-stream-to-all-components' },
31
+ )
32
+
33
+ when 'turbo-stream-to-element'
34
+ SvelteOnRails::TurboStream.send(
35
+ nil,
36
+ { message: "Sent by TurboStream: äöü🤣🌴🌍漢字", class: 'turbo-stream-to-element' },
37
+ selector: '.my-custom-class',
38
+ event: 'my-custom-event'
29
39
  )
30
- render plain: 'component-action streamed'
40
+
31
41
  end
32
42
 
33
43
  end
@@ -0,0 +1,17 @@
1
+ import { createConsumer } from "@rails/actioncable"
2
+ import {dispatchSvelteStreamEvent, actionCableDebugLog} from '@csedl/svelte-on-rails'
3
+
4
+ const consumer = createConsumer()
5
+
6
+ consumer.subscriptions.create("SvelteOnRailsChannel", {
7
+ connected() {
8
+ actionCableDebugLog("Connected to SvelteOnRailsChannel")
9
+ },
10
+ disconnected() {
11
+ actionCableDebugLog("Disconnected from SvelteOnRailsChannel")
12
+ },
13
+ received(data) {
14
+ actionCableDebugLog("Received:", data)
15
+ dispatchSvelteStreamEvent(data)
16
+ }
17
+ })
@@ -1,37 +1,31 @@
1
1
  <script lang="ts">
2
2
  import axios from "axios";
3
3
  import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
4
- import { onMount } from "svelte";
5
4
 
6
- let counter = $state(0)
7
5
  let results = $state([])
8
- let incrBtn
9
6
 
10
- onMount(() => {
11
- incrBtn.addEventListener('click', increaseCounter)
12
- });
13
-
14
- function callChannelAction(params) {
7
+ function callChannelAction(action) {
15
8
  results = []
16
- axios.get(`/svelte_on_rails_hello_world/turbo_stream_action?${params}`)
9
+ axios.get(`/svelte_on_rails_hello_world/turbo_stream_action?stream=${action}`)
17
10
  .then(function (response) {
18
- results.push(
19
- {
20
- text: `server action called, status: ${response.status}`,
21
- class: 'called-for-action'
22
- })
11
+ console.log(`server action called, status: ${response.status}`)
23
12
  })
24
13
  }
25
14
 
26
- function increaseCounter() {
27
- counter += 1
28
- }
29
-
30
15
  const handleCableEvent = (ev) => {
31
16
  results.push(
32
17
  {
33
18
  text: `Message received from Server: ${JSON.stringify(ev.detail.message)}`,
34
- class: 'stream-action-received'
19
+ class: ev.detail.class
20
+ }
21
+ )
22
+ };
23
+
24
+ function handleElementEvent(ev) {
25
+ results.push(
26
+ {
27
+ text: `Element triggered from Server: ${JSON.stringify(ev.detail.message)}`,
28
+ class: ev.detail.class
35
29
  }
36
30
  )
37
31
  };
@@ -42,16 +36,18 @@
42
36
 
43
37
  <p>Actions that are triggered by SvelteOnRails::TurboStream channel from the server</p>
44
38
 
45
- <button onstream-action="{() => callChannelAction('increase=true')}">Call increase action over Channel</button>
46
-
47
- <button bind:this={incrBtn} class="counter-button" onclick="{increaseCounter}">increase {counter}</button>
48
-
49
- <button class="call-channel-action" onclick="{callChannelAction}">Action</button>
50
-
51
- <button onclick="{() => callChannelAction('action_cable=true')}">Call ActionCable Action</button>
52
-
53
- <ul class="results">
54
- {#each results as result}
55
- <li class="{result.class}">{result.text}</li>
56
- {/each}
57
- </ul>
39
+ <button class="action-cable-to-component" onclick="{() => callChannelAction('action-cable-to-component')}">ActionCable to component</button>
40
+ <button class="action-cable-to-element" onclick="{() => callChannelAction('action-cable-to-element')}">ActionCable to element</button>
41
+ <button class="turbo-stream-to-all-components" onclick="{() => callChannelAction('turbo-stream-to-all-components')}">TurboStream to all components</button>
42
+ <button class="turbo-stream-to-element" onclick="{() => callChannelAction('turbo-stream-to-element')}">TurboStream to element</button>
43
+
44
+ <span class="my-custom-class" onmy-custom-event="{handleElementEvent}"></span>
45
+
46
+ <div class="results-box">
47
+ <p>Result:</p>
48
+ <ul class="results">
49
+ {#each results as result}
50
+ <li class="{result.class}">{@html result.text}</li>
51
+ {/each}
52
+ </ul>
53
+ </div>
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: 5.1.0
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Sedlmair
@@ -59,6 +59,7 @@ files:
59
59
  - templates/rails_vite_hello_world/app/frontend/images/svelte-on-rails-hello-world-england.png
60
60
  - templates/rails_vite_hello_world/app/frontend/images/svelte-on-rails-hello-world-face-smile-wink.svg
61
61
  - templates/rails_vite_hello_world/app/frontend/images/svelte-on-rails-hello-world-switzerland.jpg
62
+ - templates/rails_vite_hello_world/app/frontend/initializers/actionCable.js
62
63
  - templates/rails_vite_hello_world/app/frontend/javascript/components/JavascriptImport.svelte
63
64
  - templates/rails_vite_hello_world/app/frontend/javascript/components/JpgImport.svelte
64
65
  - templates/rails_vite_hello_world/app/frontend/javascript/components/ParentWithChild.svelte