inertia_cable 0.2.1 → 0.3.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: 467488f15b5926bd5b36c68bf873f04d80a9d1d3196f05b8c610dd7e5bbfed1c
4
- data.tar.gz: 3d26e273740a16678aea2b6491afe4af7463c7fa492974d2bdccc393787cdb09
3
+ metadata.gz: 1a8763f30ddbc3cc7e0fc2ade8280ca8e9c57bcd09bbc7eeb9ac4417071b1608
4
+ data.tar.gz: b98b8c3d8194fcf5f7cc563e7e7ed82e1e923570f5dda6e7c23803abe1caffb1
5
5
  SHA512:
6
- metadata.gz: 86b16433049aeedf34d478a398531666dec745556bdc21a2090e0d0023658a11aecab505a02ca7727f9e7d60442079a47e009e78cb778c01a37462b862578fc9
7
- data.tar.gz: 3001e9c9acc8cfaf12d1287caf84700bf43fb4c4a7a28cbec30a9fa4a51ffdb890da1b856859bbe6a73d1ddcf504dd5e9feb23dabda698e61647ad8c5ca46dfc
6
+ metadata.gz: cf7a607e798158e08e5d84a58b33256471cbff94710625cec8f4bfd55ea53e1b7874376f23e99c46b043a805c9942d5584ab53d2db1af73ed3ffcaec17ee3fea
7
+ data.tar.gz: 35224b191abc4f06d2ae4a726daab3a7f9522a0cefa19244e2bd1fbe0f51dd6936966ce2475f3aedcc49042bd7432561cbc2f155abf00f3ac82538c536eb96ca
data/README.md CHANGED
@@ -52,6 +52,14 @@ Optionally run the install generator:
52
52
  rails generate inertia_cable:install
53
53
  ```
54
54
 
55
+ Version 0.3 targets **Inertia.js 3 and React 19**, and ships ES modules only. Applications on Inertia 1 or 2 should stay on `@inertia-cable/react@0.2` until upgrading.
56
+
57
+ ### Upgrading from 0.2
58
+
59
+ Upgrade `@inertiajs/react` to `^3.0.0`, React and React DOM to `^19.0.0`, and `inertia_rails` to `~> 3.19` or newer compatible 3.x. Follow the [Inertia Rails v3 upgrade guide](https://inertia-rails.dev/guide/upgrade-guide) for application configuration changes. Then upgrade `inertia_cable` and `@inertia-cable/react` to 0.3.
60
+
61
+ The hook and Ruby broadcast APIs are unchanged. Use ESM `import` statements; CommonJS `require()` is no longer supported. Background refreshes now preserve existing Inertia page validation errors, including reconnect catch-up reloads.
62
+
55
63
  ## Quick Start
56
64
 
57
65
  ### 1. Model — declare what broadcasts
@@ -418,13 +426,24 @@ end
418
426
 
419
427
  Optionally coalesce rapid broadcasts using Rails cache. **Not used by default** — the client-side 100ms debounce handles most cases.
420
428
 
421
- Requires a shared cache store (Redis, Memcached, or SolidCache) in multi-process deployments.
429
+ Server-side debounce is useful when a single operation triggers many model callbacks (e.g., bulk imports, cascading updates) and you want to reduce the number of ActionCable messages sent. The client-side debounce already coalesces rapid reloads into one, so server-side debounce is only needed when the volume of WebSocket messages itself is a concern.
430
+
431
+ Requires a shared cache store (Redis, Memcached, or SolidCache) in multi-process deployments. `MemoryStore` (the Rails default) only works within a single process.
422
432
 
423
433
  ```ruby
424
- InertiaCable.debounce_delay = 0.5 # seconds (default)
434
+ # Via the model DSL
435
+ broadcasts_to :board, debounce: true # uses InertiaCable.debounce_delay (0.5s)
436
+ broadcasts_to :board, debounce: 1.0 # custom delay in seconds
425
437
 
438
+ # Via instance methods
439
+ post.broadcast_refresh_later_to(board, debounce: 2.0)
440
+
441
+ # Direct usage
426
442
  InertiaCable::Debounce.broadcast("my_stream", payload)
427
443
  InertiaCable::Debounce.broadcast("my_stream", payload, delay: 2.0)
444
+
445
+ # Configure the global default
446
+ InertiaCable.debounce_delay = 0.5 # seconds (default)
428
447
  ```
429
448
 
430
449
  ---
@@ -475,6 +494,21 @@ end
475
494
 
476
495
  All three accept splat streamables: `assert_broadcasts_on(chat, :messages) { ... }`
477
496
 
497
+ ### Broadcast callbacks
498
+
499
+ `InertiaCable.on_broadcast` registers a callback that fires for every broadcast (including debounced ones). The test helpers use this internally, but you can use it for custom instrumentation or logging:
500
+
501
+ ```ruby
502
+ callback = ->(stream_name, payload) {
503
+ Rails.logger.info "[InertiaCable] #{payload[:type]} on #{stream_name}"
504
+ }
505
+
506
+ InertiaCable.on_broadcast(&callback)
507
+
508
+ # Later, to unregister:
509
+ InertiaCable.off_broadcast(&callback)
510
+ ```
511
+
478
512
  ---
479
513
 
480
514
  ## Configuration
@@ -489,7 +523,7 @@ InertiaCable.debounce_delay = 0.5 # server-side debounce
489
523
 
490
524
  ## Security
491
525
 
492
- Stream tokens are HMAC-SHA256 signed using `secret_key_base` and verified server-side on subscription. Invalid tokens are rejected. No data travels over the WebSocket actual data is fetched via Inertia's normal HTTP cycle, which runs through your controller and its authorization logic on every reload. Token rotation follows `secret_key_base` rotation.
526
+ Stream tokens are HMAC-SHA256 signed using `secret_key_base` and verified server-side on subscription. Invalid tokens are rejected. Refresh signals carry model metadata and any `extra` fields over the WebSocket; page props are fetched through your controller and its authorization logic on every reload. Direct messages send their `data` payload over the WebSocket without running controller authorization again. Only issue stream tokens to authorized users, and ensure every subscriber is allowed to receive the stream's metadata and direct messages. Token rotation follows `secret_key_base` rotation.
493
527
 
494
528
  ---
495
529
 
@@ -508,17 +542,9 @@ inertia_cable_stream(@post.board) # ✓ signs gid://app/Board/1
508
542
  inertia_cable_stream(@post) # ✗ signs gid://app/Post/1
509
543
  ```
510
544
 
511
- ### `only`/`except` crashes
545
+ ### Reloading selected props
512
546
 
513
- Always pass arrays, never `undefined`:
514
-
515
- ```tsx
516
- // Bad
517
- useInertiaCable(stream, { only: someCondition ? ['messages'] : undefined })
518
-
519
- // Good
520
- useInertiaCable(stream, { ...(someCondition ? { only: ['messages'] } : {}) })
521
- ```
547
+ Pass arrays for `only` and `except`. Omitted or `undefined` filters are safely ignored. Without either filter, refresh signals reload all normally included props.
522
548
 
523
549
  ### Server-side debounce not working across processes
524
550
 
@@ -534,16 +560,24 @@ config.cache_store = :redis_cache_store, { url: ENV["REDIS_URL"] }
534
560
 
535
561
  - Ruby >= 3.1
536
562
  - Rails >= 7.0 (ActionCable, ActiveJob, ActiveSupport)
537
- - Inertia.js >= 1.0 with React (`@inertiajs/react`)
563
+ - Inertia.js 3.x (`@inertiajs/react`) with React and React DOM 19.x
564
+ - `inertia_rails` >= 3.19, < 4 for Inertia.js 3 applications
565
+ - An ESM-capable frontend build setup (such as Vite)
538
566
  - ActionCable configured with Redis or SolidCable (production) or async (development)
539
567
 
540
568
  ## Development
541
569
 
542
570
  ```bash
543
571
  bundle install && bundle exec rspec # Ruby specs
544
- cd frontend && npm install && npm test # Frontend
572
+ cd frontend
573
+ npm ci
574
+ npm run typecheck
575
+ npm test
576
+ npm run build
545
577
  ```
546
578
 
579
+ The integration app imports the built package through a local file dependency. After building `frontend`, run `npm ci`, `npm run check`, and `npx vite build` in `integration_test`. Rebuild the package after changing its source; use `npm run dev` in `frontend` while developing the example app.
580
+
547
581
  ## License
548
582
 
549
583
  MIT
@@ -6,6 +6,7 @@ module InertiaCable
6
6
  return if Rails.cache.exist?(cache_key)
7
7
 
8
8
  Rails.cache.write(cache_key, true, expires_in: delay)
9
+ InertiaCable.broadcast_callbacks.each { |cb| cb.call(stream_name, payload) }
9
10
  ActionCable.server.broadcast(stream_name, payload)
10
11
  end
11
12
  end
@@ -1,3 +1,3 @@
1
1
  module InertiaCable
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inertia_cable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cole Robertson
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-02-03 00:00:00.000000000 Z
10
+ date: 2026-09-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: actioncable