dexiecable 2.0.0.alpha1 → 2.0.0.alpha3
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 +40 -2
- data/lib/dexiecable/dexie_channel.rb +40 -8
- data/lib/dexiecable/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2c2de6d52cf60491a659aebc8452a88ca8b8878142d08e842fadc8fb4bb1050b
|
|
4
|
+
data.tar.gz: 6be72c303e815a4809aff6b88a718b3e9ec1df8d5ebd341af03768225ee86bc3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ac607ef7627a7a0562459042bcc8b23244362553624cb2f7543a7997430842c5185d5c889b8557c3ad28f10265d286f7a557a1ce76c397473adc97ead82b13d5
|
|
7
|
+
data.tar.gz: 1386543cc03df9409d17f184a8e1b4b80e85f993663009a32324da9b8e79561000c907c42e25c84c683bef4d4f11e525a5c1cd6dda58a0817595d53417880786
|
data/README.md
CHANGED
|
@@ -73,7 +73,7 @@ setConsumer(createConsumer("wss://example.com/cable"));
|
|
|
73
73
|
|
|
74
74
|
### DexieChannel
|
|
75
75
|
|
|
76
|
-
DexieCable ships one channel — `DexieChannel` — so you
|
|
76
|
+
DexieCable ships one channel — `DexieChannel` — so you don't need to define channels yourself. Every Dexie broadcast goes through it, and you can reopen it to add custom actions or push initial data.
|
|
77
77
|
|
|
78
78
|
Stream tokens are signed with the application secret, so a client can only subscribe to streams the server has issued for it:
|
|
79
79
|
|
|
@@ -85,7 +85,7 @@ For an ActiveRecord model it signs the record's GlobalID:
|
|
|
85
85
|
|
|
86
86
|
```ruby
|
|
87
87
|
DexieChannel.stream_token_for(current_user)
|
|
88
|
-
# => "
|
|
88
|
+
# => "signed token for gid://app/User/1"
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
Send that token to the client (render it in a view, return it from an endpoint, etc.) and add it to the subscription:
|
|
@@ -107,6 +107,44 @@ subscription.removeStream(userStream);
|
|
|
107
107
|
subscription.removeAllStreams();
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
#### Extending DexieChannel
|
|
111
|
+
|
|
112
|
+
To add custom actions or push initial data, reopen `DexieChannel` in your app:
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# config/initializers/dexiecable.rb
|
|
116
|
+
class DexieCable::DexieChannel
|
|
117
|
+
# Push a snapshot when a private stream is added.
|
|
118
|
+
def subscribed_to(record, params)
|
|
119
|
+
case record
|
|
120
|
+
when User
|
|
121
|
+
table("notifications").bulkAdd(record.notifications.map(&:as_json_for_dexie))
|
|
122
|
+
when Conversation
|
|
123
|
+
table("messages").bulkAdd(record.messages.where("seq_id > ?", params[:last_seq_id]).map(&:as_json_for_dexie))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Any public method is a custom action the client can perform.
|
|
128
|
+
def mark_as_read(data)
|
|
129
|
+
Message.find(data["id"]).update!(read: true)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The client still subscribes to `DexieCable::DexieChannel`, so no extra client config is needed:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
const subscription = subscribe(db);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Pass params from the client when adding a stream:
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
subscription.addStream(userStream, { last_seq_id: 100 });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`subscribed_to` runs after the stream is opened, and `table(...)` transmits to just this subscriber — so the snapshot arrives before any live mutation. Custom actions are triggered like any ActionCable action: `subscription.perform("mark_as_read", { id: 42 })`.
|
|
147
|
+
|
|
110
148
|
#### Public streams
|
|
111
149
|
|
|
112
150
|
For data that's public (a global feed, announcements, etc.), skip the signature. Use a string target — it's namespaced under `public:` automatically:
|
|
@@ -13,6 +13,22 @@ module DexieCable
|
|
|
13
13
|
# # public (no signature, namespaced under "public:")
|
|
14
14
|
# subscription.addPublicStream("feed")
|
|
15
15
|
#
|
|
16
|
+
# Reopen this channel in your app to push initial data or add custom
|
|
17
|
+
# actions:
|
|
18
|
+
#
|
|
19
|
+
# class DexieCable::DexieChannel
|
|
20
|
+
# def subscribed_to(record, params)
|
|
21
|
+
# case record
|
|
22
|
+
# when User
|
|
23
|
+
# table("notifications").bulkAdd(record.notifications.map(&:as_json_for_dexie))
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# def my_custom_action(data)
|
|
28
|
+
# # ...
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
16
32
|
class DexieChannel < ActionCable::Channel::Base
|
|
17
33
|
PUBLIC_STREAM_PREFIX = "public:"
|
|
18
34
|
|
|
@@ -40,11 +56,11 @@ module DexieCable
|
|
|
40
56
|
Query.new(self, name)
|
|
41
57
|
end
|
|
42
58
|
|
|
43
|
-
# Returns a signed token for
|
|
44
|
-
#
|
|
59
|
+
# Returns a signed token for +target+ (a record or other private
|
|
60
|
+
# target). Send it to the client, which passes it to
|
|
45
61
|
# +subscription.addStream+.
|
|
46
62
|
def self.stream_token_for(target)
|
|
47
|
-
verifier.generate(
|
|
63
|
+
verifier.generate(target.respond_to?(:to_gid_param) ? target.to_gid_param : target.to_s)
|
|
48
64
|
end
|
|
49
65
|
|
|
50
66
|
def self.verifier
|
|
@@ -56,13 +72,19 @@ module DexieCable
|
|
|
56
72
|
end
|
|
57
73
|
|
|
58
74
|
def add_stream(data)
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
target = verified_target(data["stream"])
|
|
76
|
+
return unless target
|
|
77
|
+
|
|
78
|
+
stream_for target
|
|
79
|
+
params = data.except("action", "stream").with_indifferent_access
|
|
80
|
+
subscribed_to(resolve_subscribe_target(target), params)
|
|
61
81
|
end
|
|
62
82
|
|
|
63
83
|
def remove_stream(data)
|
|
64
|
-
|
|
65
|
-
|
|
84
|
+
target = verified_target(data["stream"])
|
|
85
|
+
return unless target
|
|
86
|
+
|
|
87
|
+
stop_stream_from self.class.broadcasting_for(target)
|
|
66
88
|
end
|
|
67
89
|
|
|
68
90
|
def remove_all_streams(_data)
|
|
@@ -79,18 +101,28 @@ module DexieCable
|
|
|
79
101
|
stop_stream_from public_stream_name(name) if name.present?
|
|
80
102
|
end
|
|
81
103
|
|
|
104
|
+
# Override by reopening the channel to push initial data when a private
|
|
105
|
+
# stream is added. +record+ is the resolved target and +params+ are any
|
|
106
|
+
# extra params sent from the client.
|
|
107
|
+
def subscribed_to(_record, _params)
|
|
108
|
+
end
|
|
109
|
+
|
|
82
110
|
private
|
|
83
111
|
|
|
84
112
|
def public_stream_name(name)
|
|
85
113
|
self.class.broadcasting_for("#{PUBLIC_STREAM_PREFIX}#{name}")
|
|
86
114
|
end
|
|
87
115
|
|
|
88
|
-
def
|
|
116
|
+
def verified_target(token)
|
|
89
117
|
return unless token.present?
|
|
90
118
|
|
|
91
119
|
self.class.verifier.verify(token)
|
|
92
120
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
|
93
121
|
nil
|
|
94
122
|
end
|
|
123
|
+
|
|
124
|
+
def resolve_subscribe_target(target)
|
|
125
|
+
target.start_with?("gid://") ? GlobalID::Locator.locate(target) : target
|
|
126
|
+
end
|
|
95
127
|
end
|
|
96
128
|
end
|
data/lib/dexiecable/version.rb
CHANGED