inertia_cable 0.2.2 → 0.4.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 +4 -4
- data/README.md +66 -14
- data/lib/inertia_cable/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65880c281b47d6ea0c032a6a44adb84554f9927668d817c589b8c16c53db74a5
|
|
4
|
+
data.tar.gz: ae6a35e548370cce9572c6e0a404dbc527c7e2ec419996defe36f72b258aac38
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: decce67595c86d5dc150feb10a2e505612d1d64aaaeded7eb2b22ca645c30f5e84697cbd22d5bf37304dcb71897ad3d2d34e52a26758cea81f14a37444ac188c
|
|
7
|
+
data.tar.gz: 7150f27fc86c68df0cb96fcfd026c8122c0cadce8e355c71b6d22c80cb4a13ef45868a1d9a4e32ddd2383fe610a08a2e72f697d8a8007737215a16c5f7d35e18
|
data/README.md
CHANGED
|
@@ -52,6 +52,18 @@ Optionally run the install generator:
|
|
|
52
52
|
rails generate inertia_cable:install
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
Version 0.4 targets **Inertia.js 3.7+ 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.3
|
|
58
|
+
|
|
59
|
+
Upgrade `@inertiajs/react` to `^3.7.0`. Existing subscriptions keep working. The new coordinator uses Inertia's built-in rest-mode polling; the Ruby broadcast protocol is unchanged and works with the 0.3 gem.
|
|
60
|
+
|
|
61
|
+
### Upgrading from 0.2
|
|
62
|
+
|
|
63
|
+
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.
|
|
64
|
+
|
|
65
|
+
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.
|
|
66
|
+
|
|
55
67
|
## Quick Start
|
|
56
68
|
|
|
57
69
|
### 1. Model — declare what broadcasts
|
|
@@ -243,7 +255,47 @@ The token is verified server-side when the client subscribes — invalid or tamp
|
|
|
243
255
|
|
|
244
256
|
### `useInertiaCable(signedStreamName, options?)`
|
|
245
257
|
|
|
246
|
-
Returns `{ connected }`
|
|
258
|
+
Returns `{ connected, status, refreshing, lastRefreshedAt, refreshError }`. `status` is `disabled`, `connecting`, `connected`, `reconnecting`, or `rejected`. `lastRefreshedAt` is a completion timestamp in milliseconds, initially `null`; a connected socket alone does not prove fresh page data. `onRejected` observes subscription rejection.
|
|
259
|
+
|
|
260
|
+
The optional `refresh(context)` callback replaces the default reload. Its context contains `reason` (`broadcast` or `reconnect`), `only`, and `except`. Return a promise to track completion/failure in this hook, or return void when another coordinator owns freshness. `onRefresh(payload)` remains an observer of broadcast signals and does not replace reloads.
|
|
261
|
+
|
|
262
|
+
### Shared refresh coordination
|
|
263
|
+
|
|
264
|
+
Use one coordinator per mounted page and share it across subscriptions:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import { router } from '@inertiajs/react'
|
|
268
|
+
import { useInertiaCable, useInertiaRefresh } from '@inertia-cable/react'
|
|
269
|
+
|
|
270
|
+
const live = useInertiaRefresh({
|
|
271
|
+
scope: `${site.id}:${pageUrl}`,
|
|
272
|
+
only: ['orders', 'shipments'],
|
|
273
|
+
debounce: 100,
|
|
274
|
+
pollInterval: 60_000,
|
|
275
|
+
})
|
|
276
|
+
useInertiaCable(orderStream, {
|
|
277
|
+
only: ['orders'],
|
|
278
|
+
debounce: 0,
|
|
279
|
+
refresh: ({ only }) => live.refresh(only),
|
|
280
|
+
onConnected: () => live.refresh(),
|
|
281
|
+
})
|
|
282
|
+
useInertiaCable(shipmentStream, {
|
|
283
|
+
only: ['shipments'],
|
|
284
|
+
debounce: 0,
|
|
285
|
+
refresh: ({ only }) => live.refresh(only),
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
// Route scope-changing controls through the barrier.
|
|
289
|
+
const selectSite = (id: number) => live.visit(() => {
|
|
290
|
+
router.get('/operations', { site_id: id }, { preserveState: true })
|
|
291
|
+
})
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
`useInertiaRefresh({ scope, only, enabled?, debounce?, pollInterval? })` returns `refresh(keys?)`, `visit(run)`, `refreshing`, `lastRefreshedAt`, and `error`. It unions invalidated prop keys, permits one owned reload at a time, and retains a trailing refresh when signals arrive during a request. The default debounce is 100ms; polling is opt-in. Hidden tabs pause polling and catch up when visible. An optional `onConnected` catch-up also covers changes between the initial HTTP response and subscription.
|
|
295
|
+
|
|
296
|
+
Use `live`'s freshness fields when delegating with a void callback. `scope` must change with the selected site/filter. `visit(run)` cancels the coordinator's request or waits for response processing to finish before running navigation, preserving the original closure and callbacks. Automatic router listeners also yield to other visits, but cannot delay a visit already started elsewhere: route same-page scope changes through `visit`. It never cancels unrelated requests. Inertia continues to own HTTP, prop merging, form state, and polling.
|
|
297
|
+
|
|
298
|
+
For non-hook integration, `createInertiaRefresh({ only, debounce?, pollInterval? })` exposes the same `refresh`/`visit` operations plus `getSnapshot()`, `subscribe(listener)` (returns unsubscribe), and `dispose()`. Create it only in a browser lifecycle and always dispose it on scope changes/unmount. The React hook handles this lifecycle, including SSR.
|
|
247
299
|
|
|
248
300
|
```tsx
|
|
249
301
|
const { connected } = useInertiaCable(cable_stream, {
|
|
@@ -515,7 +567,7 @@ InertiaCable.debounce_delay = 0.5 # server-side debounce
|
|
|
515
567
|
|
|
516
568
|
## Security
|
|
517
569
|
|
|
518
|
-
Stream tokens are HMAC-SHA256 signed using `secret_key_base` and verified server-side on subscription. Invalid tokens are rejected.
|
|
570
|
+
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.
|
|
519
571
|
|
|
520
572
|
---
|
|
521
573
|
|
|
@@ -534,17 +586,9 @@ inertia_cable_stream(@post.board) # ✓ signs gid://app/Board/1
|
|
|
534
586
|
inertia_cable_stream(@post) # ✗ signs gid://app/Post/1
|
|
535
587
|
```
|
|
536
588
|
|
|
537
|
-
###
|
|
538
|
-
|
|
539
|
-
Always pass arrays, never `undefined`:
|
|
540
|
-
|
|
541
|
-
```tsx
|
|
542
|
-
// Bad
|
|
543
|
-
useInertiaCable(stream, { only: someCondition ? ['messages'] : undefined })
|
|
589
|
+
### Reloading selected props
|
|
544
590
|
|
|
545
|
-
|
|
546
|
-
useInertiaCable(stream, { ...(someCondition ? { only: ['messages'] } : {}) })
|
|
547
|
-
```
|
|
591
|
+
Pass arrays for `only` and `except`. Omitted or `undefined` filters are safely ignored. Without either filter, refresh signals reload all normally included props.
|
|
548
592
|
|
|
549
593
|
### Server-side debounce not working across processes
|
|
550
594
|
|
|
@@ -560,16 +604,24 @@ config.cache_store = :redis_cache_store, { url: ENV["REDIS_URL"] }
|
|
|
560
604
|
|
|
561
605
|
- Ruby >= 3.1
|
|
562
606
|
- Rails >= 7.0 (ActionCable, ActiveJob, ActiveSupport)
|
|
563
|
-
- Inertia.js >=
|
|
607
|
+
- Inertia.js >= 3.7, < 4 (`@inertiajs/react`) with React and React DOM 19.x
|
|
608
|
+
- `inertia_rails` >= 3.19, < 4 for Inertia.js 3 applications
|
|
609
|
+
- An ESM-capable frontend build setup (such as Vite)
|
|
564
610
|
- ActionCable configured with Redis or SolidCable (production) or async (development)
|
|
565
611
|
|
|
566
612
|
## Development
|
|
567
613
|
|
|
568
614
|
```bash
|
|
569
615
|
bundle install && bundle exec rspec # Ruby specs
|
|
570
|
-
cd frontend
|
|
616
|
+
cd frontend
|
|
617
|
+
npm ci
|
|
618
|
+
npm run typecheck
|
|
619
|
+
npm test
|
|
620
|
+
npm run build
|
|
571
621
|
```
|
|
572
622
|
|
|
623
|
+
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.
|
|
624
|
+
|
|
573
625
|
## License
|
|
574
626
|
|
|
575
627
|
MIT
|
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.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cole Robertson
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: actioncable
|
|
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
104
104
|
- !ruby/object:Gem::Version
|
|
105
105
|
version: '0'
|
|
106
106
|
requirements: []
|
|
107
|
-
rubygems_version: 3.6.
|
|
107
|
+
rubygems_version: 3.6.9
|
|
108
108
|
specification_version: 4
|
|
109
109
|
summary: ActionCable broadcast DSL for Inertia Rails
|
|
110
110
|
test_files: []
|