Skip to content

Commit 1274550

Browse files
authored
improvement: Add support for relay_id_translation on GraphQL subscriptions (#349)
1 parent 8fd8cc1 commit 1274550

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

documentation/dsls/DSL-AshGraphql.Domain.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ end
538538
| [`action_types`](#graphql-subscriptions-subscribe-action_types){: #graphql-subscriptions-subscribe-action_types } | `list(atom) \| atom` | | The type of actions the subsciption should listen to. |
539539
| [`read_action`](#graphql-subscriptions-subscribe-read_action){: #graphql-subscriptions-subscribe-read_action } | `atom` | | The read action to use for reading data |
540540
| [`hide_inputs`](#graphql-subscriptions-subscribe-hide_inputs){: #graphql-subscriptions-subscribe-hide_inputs } | `list(atom)` | `[]` | A list of inputs to hide from the subscription, usable if the read action has arguments. |
541+
| [`relay_id_translations`](#graphql-subscriptions-subscribe-relay_id_translations){: #graphql-subscriptions-subscribe-relay_id_translations } | `keyword` | `[]` | A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. See the [Relay guide](/documentation/topics/relay.md#translating-relay-global-ids-passed-as-arguments) for more. |
541542
| [`meta`](#graphql-subscriptions-subscribe-meta){: #graphql-subscriptions-subscribe-meta } | `keyword` | | A keyword list of metadata to include in the subscription. |
542543

543544

documentation/dsls/DSL-AshGraphql.Resource.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ end
558558
| [`action_types`](#graphql-subscriptions-subscribe-action_types){: #graphql-subscriptions-subscribe-action_types } | `list(atom) \| atom` | | The type of actions the subsciption should listen to. |
559559
| [`read_action`](#graphql-subscriptions-subscribe-read_action){: #graphql-subscriptions-subscribe-read_action } | `atom` | | The read action to use for reading data |
560560
| [`hide_inputs`](#graphql-subscriptions-subscribe-hide_inputs){: #graphql-subscriptions-subscribe-hide_inputs } | `list(atom)` | `[]` | A list of inputs to hide from the subscription, usable if the read action has arguments. |
561+
| [`relay_id_translations`](#graphql-subscriptions-subscribe-relay_id_translations){: #graphql-subscriptions-subscribe-relay_id_translations } | `keyword` | `[]` | A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. See the [Relay guide](/documentation/topics/relay.md#translating-relay-global-ids-passed-as-arguments) for more. |
561562
| [`meta`](#graphql-subscriptions-subscribe-meta){: #graphql-subscriptions-subscribe-meta } | `keyword` | | A keyword list of metadata to include in the subscription. |
562563

563564

lib/resource/resource.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,7 @@ defmodule AshGraphql.Resource do
13061306
action_middleware ++
13071307
domain_middleware(domain) ++
13081308
metadata_middleware(subscription.meta) ++
1309+
id_translation_middleware(subscription.relay_id_translations, relay_ids?) ++
13091310
[
13101311
{{AshGraphql.Graphql.Resolver, :resolve},
13111312
{domain, resource, subscription, relay_ids?}}

lib/resource/subscription.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ defmodule AshGraphql.Resource.Subscription do
88
:read_action,
99
:actor,
1010
:hide_inputs,
11+
:relay_id_translations,
1112
:meta
1213
]
1314

@@ -40,6 +41,13 @@ defmodule AshGraphql.Resource.Subscription do
4041
"A list of inputs to hide from the subscription, usable if the read action has arguments.",
4142
default: []
4243
],
44+
relay_id_translations: [
45+
type: :keyword_list,
46+
doc: """
47+
A keyword list indicating arguments or attributes that have to be translated from global Relay IDs to internal IDs. See the [Relay guide](/documentation/topics/relay.md#translating-relay-global-ids-passed-as-arguments) for more.
48+
""",
49+
default: []
50+
],
4351
meta: [
4452
type: :keyword_list,
4553
doc: "A keyword list of metadata to include in the subscription."

test/subscription_test.exs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,61 @@ defmodule AshGraphql.SubscriptionTest do
400400
subscription_data["subscribableEventsWithArguments"]["created"]["id"]
401401
end
402402

403+
test "can subscribe to read actions that take arguments with relay style id's" do
404+
subscribable =
405+
RelaySubscribable
406+
|> Ash.Changeset.for_create(:create, %{text: "foo", topic: "news", actor_id: 1},
407+
actor: @admin
408+
)
409+
|> Ash.create!()
410+
411+
relay_id = AshGraphql.Resource.encode_relay_id(subscribable)
412+
413+
subscription = """
414+
subscription WithIdFilter($subscribableId: ID!) {
415+
subscribableEventsRelayWithIdFilter(subscribableId: $subscribableId) {
416+
updated {
417+
id
418+
text
419+
}
420+
}
421+
}
422+
"""
423+
424+
assert {:ok, %{"subscribed" => topic}} =
425+
Absinthe.run(
426+
subscription,
427+
RelaySchema,
428+
variables: %{"subscribableId" => relay_id},
429+
context: %{actor: @admin, pubsub: PubSub}
430+
)
431+
432+
update_mutation = """
433+
mutation UpdateSubscribable($id: ID! $input: UpdateRelaySubscribableInput) {
434+
updateRelaySubscribable(id: $id, input: $input) {
435+
result{
436+
id
437+
text
438+
}
439+
errors{
440+
message
441+
}
442+
}
443+
}
444+
"""
445+
446+
assert {:ok, %{data: _mutation_result}} =
447+
Absinthe.run(update_mutation, RelaySchema,
448+
variables: %{"id" => relay_id, "input" => %{"text" => "updated"}},
449+
context: %{actor: @admin}
450+
)
451+
452+
assert_receive({^topic, %{data: subscription_data}})
453+
454+
assert relay_id ==
455+
subscription_data["subscribableEventsRelayWithIdFilter"]["updated"]["id"]
456+
end
457+
403458
test "can subscribe on the domain" do
404459
actor1 = %{
405460
id: 1,

test/support/resources/relay_subscribable.ex

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ defmodule AshGraphql.Test.RelaySubscribable do
1212
type :relay_subscribable
1313

1414
mutations do
15+
update :update_relay_subscribable, :update
1516
destroy :destroy_subscribable_relay, :destroy
1617
end
1718

@@ -25,6 +26,17 @@ defmodule AshGraphql.Test.RelaySubscribable do
2526
subscribe(:subscribable_deleted_relay) do
2627
action_types(:destroy)
2728
end
29+
30+
subscribe(:subscribable_events_relay_with_arguments) do
31+
read_action(:read_with_arg)
32+
actions([:create])
33+
end
34+
35+
subscribe(:subscribable_events_relay_with_id_filter) do
36+
read_action(:read_with_id_arg)
37+
action_types([:create, :update, :destroy])
38+
relay_id_translations(subscribable_id: :relay_subscribable)
39+
end
2840
end
2941
end
3042

@@ -37,7 +49,7 @@ defmodule AshGraphql.Test.RelaySubscribable do
3749
authorize_if(expr(actor_id == ^actor(:id)))
3850
end
3951

40-
policy action([:open_read, :read_with_arg]) do
52+
policy action([:open_read, :read_with_arg, :read_with_id_arg]) do
4153
authorize_if(always())
4254
end
4355
end
@@ -65,6 +77,14 @@ defmodule AshGraphql.Test.RelaySubscribable do
6577

6678
filter(expr(topic == ^arg(:topic)))
6779
end
80+
81+
read :read_with_id_arg do
82+
argument(:subscribable_id, :uuid) do
83+
allow_nil? false
84+
end
85+
86+
filter(expr(id == ^arg(:subscribable_id)))
87+
end
6888
end
6989

7090
attributes do

0 commit comments

Comments
 (0)