diff --git a/CHANGELOG.md b/CHANGELOG.md index eca842ae..16318cf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Note: For changes to the API, see https://shopify.dev/changelog?filter=api ## Unreleased +## 14.7.0 + +- [#1347](https://github.com/Shopify/shopify-api-ruby/pull/1347) Extend webhook registration to support filters - [#1344](https://github.com/Shopify/shopify-api-ruby/pull/1344) Allow ShopifyAPI::Webhooks::Registry to update a webhook when fields or metafield_namespaces are changed. - [#1343](https://github.com/Shopify/shopify-api-ruby/pull/1343) Make ShopifyAPI::Context::scope parameter optional. `scope` defaults to empty list `[]`. - [#1348](https://github.com/Shopify/shopify-api-ruby/pull/1348) Add config option that will disable the REST API client and REST resources. New apps should use the GraphQL Admin API diff --git a/Gemfile.lock b/Gemfile.lock index c896d185..63f7e16c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - shopify_api (14.6.0) + shopify_api (14.7.0) activesupport concurrent-ruby hash_diff @@ -16,20 +16,24 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (7.1.4) + activesupport (7.1.5) base64 + benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) mutex_m + securerandom (>= 0.3) tzinfo (~> 2.0) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) ast (2.4.2) base64 (0.2.0) + benchmark (0.4.0) bigdecimal (3.1.8) byebug (11.1.3) coderay (1.1.3) @@ -50,21 +54,22 @@ GEM i18n (1.14.6) concurrent-ruby (~> 1.0) json (2.7.1) - jwt (2.9.1) + jwt (2.9.3) base64 language_server-protocol (3.17.0.3) + logger (1.6.1) method_source (1.0.0) mini_mime (1.1.5) minitest (5.15.0) mocha (1.13.0) multi_xml (0.6.0) - mutex_m (0.2.0) + mutex_m (0.3.0) netrc (0.11.0) - oj (3.16.6) + oj (3.16.7) bigdecimal (>= 3.0) ostruct (>= 0.2) openssl (3.2.0) - ostruct (0.6.0) + ostruct (0.6.1) parallel (1.24.0) parser (3.3.0.5) ast (~> 2.4.1) @@ -104,7 +109,7 @@ GEM rubocop-sorbet (0.6.11) rubocop (>= 0.90.0) ruby-progressbar (1.13.0) - securerandom (0.3.1) + securerandom (0.3.2) sorbet (0.5.11230) sorbet-static (= 0.5.11230) sorbet-runtime (0.5.11230) diff --git a/docs/usage/webhooks.md b/docs/usage/webhooks.md index 55665ebe..32b940e0 100644 --- a/docs/usage/webhooks.md +++ b/docs/usage/webhooks.md @@ -82,6 +82,17 @@ registration = ShopifyAPI::Webhooks::Registry.add_registration( ) ``` +If you need to filter the webhooks you want to receive, you can use a [webhooks filter](https://shopify.dev/docs/apps/build/webhooks/customize/filters), which can be specified on registration through the `filter` parameter. + +```ruby +registration = ShopifyAPI::Webhooks::Registry.add_registration( + topic: "products/update", + delivery_method: :http, + handler: WebhookHandler, + filter: "variants.price:>=10.00" +) +``` + **Note**: The webhooks you register with Shopify are saved in the Shopify platform, but the local `ShopifyAPI::Webhooks::Registry` needs to be reloaded whenever your server restarts. ### EventBridge and PubSub Webhooks diff --git a/lib/shopify_api/rest/resources/2024_07/webhook.rb b/lib/shopify_api/rest/resources/2024_07/webhook.rb index c78827ae..21f5bbf0 100644 --- a/lib/shopify_api/rest/resources/2024_07/webhook.rb +++ b/lib/shopify_api/rest/resources/2024_07/webhook.rb @@ -23,6 +23,7 @@ def initialize(session: ShopifyAPI::Context.active_session, from_hash: nil) @api_version = T.let(nil, T.nilable(String)) @created_at = T.let(nil, T.nilable(String)) @fields = T.let(nil, T.nilable(T::Array[T.untyped])) + @filter = T.let(nil, T.nilable(String)) @format = T.let(nil, T.nilable(String)) @id = T.let(nil, T.nilable(Integer)) @metafield_namespaces = T.let(nil, T.nilable(T::Array[T.untyped])) diff --git a/lib/shopify_api/rest/resources/2024_10/webhook.rb b/lib/shopify_api/rest/resources/2024_10/webhook.rb index c78827ae..21f5bbf0 100644 --- a/lib/shopify_api/rest/resources/2024_10/webhook.rb +++ b/lib/shopify_api/rest/resources/2024_10/webhook.rb @@ -23,6 +23,7 @@ def initialize(session: ShopifyAPI::Context.active_session, from_hash: nil) @api_version = T.let(nil, T.nilable(String)) @created_at = T.let(nil, T.nilable(String)) @fields = T.let(nil, T.nilable(T::Array[T.untyped])) + @filter = T.let(nil, T.nilable(String)) @format = T.let(nil, T.nilable(String)) @id = T.let(nil, T.nilable(Integer)) @metafield_namespaces = T.let(nil, T.nilable(T::Array[T.untyped])) diff --git a/lib/shopify_api/version.rb b/lib/shopify_api/version.rb index c2b1cb8a..9c307dce 100644 --- a/lib/shopify_api/version.rb +++ b/lib/shopify_api/version.rb @@ -2,5 +2,5 @@ # frozen_string_literal: true module ShopifyAPI - VERSION = "14.6.0" + VERSION = "14.7.0" end diff --git a/lib/shopify_api/webhooks/registration.rb b/lib/shopify_api/webhooks/registration.rb index 8cd18d54..b406aea6 100644 --- a/lib/shopify_api/webhooks/registration.rb +++ b/lib/shopify_api/webhooks/registration.rb @@ -22,18 +22,23 @@ class Registration sig { returns(T.nilable(T::Array[String])) } attr_reader :metafield_namespaces + sig { returns(T.nilable(String)) } + attr_reader :filter + sig do params(topic: String, path: String, handler: T.nilable(T.any(Handler, WebhookHandler)), fields: T.nilable(T.any(String, T::Array[String])), - metafield_namespaces: T.nilable(T::Array[String])).void + metafield_namespaces: T.nilable(T::Array[String]), + filter: T.nilable(String)).void end - def initialize(topic:, path:, handler: nil, fields: nil, metafield_namespaces: nil) + def initialize(topic:, path:, handler: nil, fields: nil, metafield_namespaces: nil, filter: nil) @topic = T.let(topic.gsub("/", "_").upcase, String) @path = path @handler = handler fields_array = fields.is_a?(String) ? fields.split(FIELDS_DELIMITER) : fields @fields = T.let(fields_array&.map(&:strip)&.compact, T.nilable(T::Array[String])) @metafield_namespaces = T.let(metafield_namespaces&.map(&:strip)&.compact, T.nilable(T::Array[String])) + @filter = filter end sig { abstract.returns(String) } @@ -54,6 +59,7 @@ def build_check_query; end current_address: T.nilable(String), fields: T::Array[String], metafield_namespaces: T::Array[String], + filter: T.nilable(String), }) end def parse_check_result(body); end @@ -88,6 +94,7 @@ def subscription_response_attributes attributes = ["id"] attributes << "includeFields" if @fields attributes << "metafieldNamespaces" if @metafield_namespaces + attributes << "filter" if @filter attributes end end diff --git a/lib/shopify_api/webhooks/registrations/event_bridge.rb b/lib/shopify_api/webhooks/registrations/event_bridge.rb index 8a3653f4..f5f02afe 100644 --- a/lib/shopify_api/webhooks/registrations/event_bridge.rb +++ b/lib/shopify_api/webhooks/registrations/event_bridge.rb @@ -14,7 +14,8 @@ def callback_address sig { override.returns(T::Hash[Symbol, String]) } def subscription_args - { arn: callback_address, includeFields: fields, metafieldNamespaces: metafield_namespaces }.compact + { arn: callback_address, includeFields: fields, + metafieldNamespaces: metafield_namespaces, filter: filter, }.compact end sig { override.params(webhook_id: T.nilable(String)).returns(String) } @@ -32,6 +33,7 @@ def build_check_query id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookEventBridgeEndpoint { @@ -51,6 +53,7 @@ def build_check_query current_address: T.nilable(String), fields: T::Array[String], metafield_namespaces: T::Array[String], + filter: T.nilable(String), }) end def parse_check_result(body) @@ -58,6 +61,7 @@ def parse_check_result(body) webhook_id = nil fields = [] metafield_namespaces = [] + filter = nil current_address = nil unless edges.empty? node = edges[0]["node"] @@ -65,9 +69,10 @@ def parse_check_result(body) current_address = node["endpoint"]["arn"].to_s fields = node["includeFields"] || [] metafield_namespaces = node["metafieldNamespaces"] || [] + filter = node["filter"].to_s end { webhook_id: webhook_id, current_address: current_address, fields: fields, - metafield_namespaces: metafield_namespaces, } + metafield_namespaces: metafield_namespaces, filter: filter, } end end end diff --git a/lib/shopify_api/webhooks/registrations/http.rb b/lib/shopify_api/webhooks/registrations/http.rb index a3c0cf48..4e4459b8 100644 --- a/lib/shopify_api/webhooks/registrations/http.rb +++ b/lib/shopify_api/webhooks/registrations/http.rb @@ -20,7 +20,8 @@ def callback_address sig { override.returns(T::Hash[Symbol, String]) } def subscription_args - { callbackUrl: callback_address, includeFields: fields, metafieldNamespaces: metafield_namespaces }.compact + { callbackUrl: callback_address, includeFields: fields, + metafieldNamespaces: metafield_namespaces, filter: filter, }.compact end sig { override.params(webhook_id: T.nilable(String)).returns(String) } @@ -38,6 +39,7 @@ def build_check_query id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookHttpEndpoint { @@ -57,6 +59,7 @@ def build_check_query current_address: T.nilable(String), fields: T::Array[String], metafield_namespaces: T::Array[String], + filter: T.nilable(String), }) end def parse_check_result(body) @@ -64,6 +67,7 @@ def parse_check_result(body) webhook_id = nil fields = [] metafield_namespaces = [] + filter = nil current_address = nil unless edges.empty? node = edges[0]["node"] @@ -76,9 +80,10 @@ def parse_check_result(body) end fields = node["includeFields"] || [] metafield_namespaces = node["metafieldNamespaces"] || [] + filter = node["filter"].to_s end { webhook_id: webhook_id, current_address: current_address, fields: fields, - metafield_namespaces: metafield_namespaces, } + metafield_namespaces: metafield_namespaces, filter: filter, } end end end diff --git a/lib/shopify_api/webhooks/registrations/pub_sub.rb b/lib/shopify_api/webhooks/registrations/pub_sub.rb index 183ba890..dc657964 100644 --- a/lib/shopify_api/webhooks/registrations/pub_sub.rb +++ b/lib/shopify_api/webhooks/registrations/pub_sub.rb @@ -18,7 +18,7 @@ def subscription_args project = project_topic_pair[0] topic = project_topic_pair[1] { pubSubProject: project, pubSubTopic: topic, includeFields: fields, - metafieldNamespaces: metafield_namespaces, }.compact + metafieldNamespaces: metafield_namespaces, filter: filter, }.compact end sig { override.params(webhook_id: T.nilable(String)).returns(String) } @@ -36,6 +36,7 @@ def build_check_query id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookPubSubEndpoint { @@ -56,6 +57,7 @@ def build_check_query current_address: T.nilable(String), fields: T::Array[String], metafield_namespaces: T::Array[String], + filter: T.nilable(String), }) end def parse_check_result(body) @@ -63,6 +65,7 @@ def parse_check_result(body) webhook_id = nil fields = [] metafield_namespaces = [] + filter = nil current_address = nil unless edges.empty? node = edges[0]["node"] @@ -71,9 +74,10 @@ def parse_check_result(body) "pubsub://#{node["endpoint"]["pubSubProject"]}:#{node["endpoint"]["pubSubTopic"]}" fields = node["includeFields"] || [] metafield_namespaces = node["metafieldNamespaces"] || [] + filter = node["filter"].to_s end { webhook_id: webhook_id, current_address: current_address, fields: fields, - metafield_namespaces: metafield_namespaces, } + metafield_namespaces: metafield_namespaces, filter: filter, } end end end diff --git a/lib/shopify_api/webhooks/registry.rb b/lib/shopify_api/webhooks/registry.rb index d6abb8d4..8cc26aab 100644 --- a/lib/shopify_api/webhooks/registry.rb +++ b/lib/shopify_api/webhooks/registry.rb @@ -19,23 +19,25 @@ class << self path: String, handler: T.nilable(T.any(Handler, WebhookHandler)), fields: T.nilable(T.any(String, T::Array[String])), + filter: T.nilable(String), metafield_namespaces: T.nilable(T::Array[String])).void end - def add_registration(topic:, delivery_method:, path:, handler: nil, fields: nil, metafield_namespaces: nil) + def add_registration(topic:, delivery_method:, path:, handler: nil, fields: nil, filter: nil, + metafield_namespaces: nil) @registry[topic] = case delivery_method when :pub_sub Registrations::PubSub.new(topic: topic, path: path, fields: fields, - metafield_namespaces: metafield_namespaces) + metafield_namespaces: metafield_namespaces, filter: filter) when :event_bridge Registrations::EventBridge.new(topic: topic, path: path, fields: fields, - metafield_namespaces: metafield_namespaces) + metafield_namespaces: metafield_namespaces, filter: filter) when :http unless handler raise Errors::InvalidWebhookRegistrationError, "Cannot create an Http registration without a handler." end Registrations::Http.new(topic: topic, path: path, handler: handler, - fields: fields, metafield_namespaces: metafield_namespaces) + fields: fields, metafield_namespaces: metafield_namespaces, filter: filter) else raise Errors::InvalidWebhookRegistrationError, "Unsupported delivery method #{delivery_method}. Allowed values: {:http, :pub_sub, :event_bridge}." @@ -223,10 +225,12 @@ def webhook_registration_needed?(client, registration) parsed_check_result = registration.parse_check_result(T.cast(check_response.body, T::Hash[String, T.untyped])) registration_fields = registration.fields || [] registration_metafield_namespaces = registration.metafield_namespaces || [] + registration_filter = registration.filter must_register = parsed_check_result[:current_address] != registration.callback_address || parsed_check_result[:fields].sort != registration_fields.sort || - parsed_check_result[:metafield_namespaces].sort != registration_metafield_namespaces.sort + parsed_check_result[:metafield_namespaces].sort != registration_metafield_namespaces.sort || + parsed_check_result[:filter] != registration_filter { webhook_id: parsed_check_result[:webhook_id], must_register: must_register } end diff --git a/test/webhooks/registry_test.rb b/test/webhooks/registry_test.rb index 6a852a9d..a2c0dec8 100644 --- a/test/webhooks/registry_test.rb +++ b/test/webhooks/registry_test.rb @@ -53,6 +53,7 @@ def setup address, fields: "field1, field2", metafield_namespaces: ["namespace1", "namespace2"], + filter: "id:*", ) # Then @@ -72,6 +73,7 @@ def setup address, fields: ["field1", "field2"], metafield_namespaces: ["namespace1", "namespace2"], + filter: "id:*", ) # Then @@ -156,6 +158,27 @@ def setup update_registration_response.body) end + define_method("test_#{protocol}_update_registration_filter_with_address_#{address}") do + # Given + setup_queries_and_responses( + [queries[protocol][:check_query], queries[protocol][:register_update_query_with_filter]], + [queries[protocol][:check_existing_response], + queries[protocol][:register_update_with_filter_response],], + ) + + # When + update_registration_response = add_and_register_webhook( + protocol, + address, + filter: "id:*", + ) + + # Then + assert(update_registration_response.success) + assert_equal(queries[protocol][:register_update_with_filter_response], + update_registration_response.body) + end + define_method("test_raises_on_#{protocol}_registration_check_error_with_address_#{address}") do # Given ShopifyAPI::Webhooks::Registry.clear @@ -412,7 +435,7 @@ def setup_queries_and_responses(queries, responses) end end - def add_and_register_webhook(protocol, address, fields: nil, metafield_namespaces: nil) + def add_and_register_webhook(protocol, address, fields: nil, metafield_namespaces: nil, filter: nil) ShopifyAPI::Webhooks::Registry.add_registration( topic: @topic, delivery_method: protocol, @@ -423,6 +446,7 @@ def add_and_register_webhook(protocol, address, fields: nil, metafield_namespace ), fields: fields, metafield_namespaces: metafield_namespaces, + filter: filter, ) update_registration_response = ShopifyAPI::Webhooks::Registry.register_all( session: @session, diff --git a/test/webhooks/registry_test_queries.rb b/test/webhooks/registry_test_queries.rb index ddb18631..c2bebe65 100644 --- a/test/webhooks/registry_test_queries.rb +++ b/test/webhooks/registry_test_queries.rb @@ -16,6 +16,7 @@ def queries id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookHttpEndpoint { @@ -38,7 +39,7 @@ def queries register_add_query: <<~QUERY, mutation webhookSubscription { - webhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {callbackUrl: "https://app-address.com/test-webhooks", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"]}) { + webhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {callbackUrl: "https://app-address.com/test-webhooks", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"], filter: "id:*"}) { userErrors { field message @@ -47,6 +48,7 @@ def queries id includeFields metafieldNamespaces + filter } } } @@ -82,6 +84,22 @@ def queries } QUERY + register_add_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + webhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {callbackUrl: "https://app-address.com/test-webhooks", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY + register_add_response: { "data" => { "webhookSubscriptionCreate" => { @@ -90,6 +108,7 @@ def queries "id" => "gid://shopify/WebhookSubscription/12345", "includeFields" => ["field1", "field2"], "metafieldNamespaces" => ["namespace1", "namespace2"], + "filter" => "id:*", }, }, }, @@ -116,6 +135,17 @@ def queries }, }, }, + register_add_with_filter_response: { + "data" => { + "webhookSubscriptionCreate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter" => "id:*", + }, + }, + }, + }, check_existing_response: { "data" => { "webhookSubscriptions" => { @@ -139,6 +169,7 @@ def queries "id" => "gid://shopify/WebhookSubscription/12345", "includeFields" => ["field1", "field2"], "metafieldNamespaces" => ["namespace1", "namespace2"], + "filter" => "id:*", "endpoint" => { "typename" => "WebhookHttpEndpoint", "callbackUrl" => "https://app-address.com/test-webhooks", @@ -192,6 +223,21 @@ def queries } } QUERY + register_update_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + webhookSubscriptionUpdate(id: "gid://shopify/WebhookSubscription/12345", webhookSubscription: {callbackUrl: "https://app-address.com/test-webhooks", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY register_update_response: { "data" => { "webhookSubscriptionUpdate" => { @@ -223,6 +269,17 @@ def queries }, }, }, + register_update_with_filter_response: { + "data" => { + "webhookSubscriptionUpdate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter" => "id:*", + }, + }, + }, + }, }, event_bridge: { check_query: @@ -234,6 +291,7 @@ def queries id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookEventBridgeEndpoint { @@ -255,7 +313,7 @@ def queries register_add_query: <<~QUERY, mutation webhookSubscription { - eventBridgeWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {arn: "test-webhooks", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"]}) { + eventBridgeWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {arn: "test-webhooks", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"], filter: "id:*"}) { userErrors { field message @@ -264,6 +322,7 @@ def queries id includeFields metafieldNamespaces + filter } } } @@ -298,6 +357,21 @@ def queries } } QUERY + register_add_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + eventBridgeWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {arn: "test-webhooks", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY register_add_response: { "data" => { "eventBridgeWebhookSubscriptionCreate" => { @@ -306,6 +380,7 @@ def queries "id" => "gid://shopify/WebhookSubscription/12345", "includeFields" => ["field1", "field2"], "metafieldNamespaces" => ["namespace1", "namespace2"], + "filter" => "id:*", }, }, }, @@ -332,6 +407,17 @@ def queries }, }, }, + register_add_with_filter_response: { + "data" => { + "eventBridgeWebhookSubscriptionCreate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter" => "id:*", + }, + }, + }, + }, check_existing_response: { "data" => { "webhookSubscriptions" => { @@ -359,6 +445,7 @@ def queries }, "includeFields" => ["field2", "field1"], "metafieldNamespaces" => ["namespace2", "namespace1"], + "filter" => "id:*", }, ], }, @@ -408,6 +495,21 @@ def queries } } QUERY + register_update_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + eventBridgeWebhookSubscriptionUpdate(id: "gid://shopify/WebhookSubscription/12345", webhookSubscription: {arn: "test-webhooks", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY register_update_response: { "data" => { "eventBridgeWebhookSubscriptionUpdate" => { @@ -438,6 +540,17 @@ def queries }, }, }, + register_update_with_filter_response: { + "data" => { + "eventBridgeWebhookSubscriptionUpdate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter" => "id:*", + }, + }, + }, + }, }, pub_sub: { check_query: @@ -449,6 +562,7 @@ def queries id includeFields metafieldNamespaces + filter endpoint { __typename ... on WebhookPubSubEndpoint { @@ -471,7 +585,7 @@ def queries register_add_query: <<~QUERY, mutation webhookSubscription { - pubSubWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {pubSubProject: "my-project-id", pubSubTopic: "my-topic-id", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"]}) { + pubSubWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {pubSubProject: "my-project-id", pubSubTopic: "my-topic-id", includeFields: ["field1", "field2"], metafieldNamespaces: ["namespace1", "namespace2"], filter: "id:*"}) { userErrors { field message @@ -480,6 +594,7 @@ def queries id includeFields metafieldNamespaces + filter } } } @@ -514,6 +629,21 @@ def queries } } QUERY + register_add_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + pubSubWebhookSubscriptionCreate(topic: SOME_TOPIC, webhookSubscription: {pubSubProject: "my-project-id", pubSubTopic: "my-topic-id", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY register_add_response: { "data" => { "pubSubWebhookSubscriptionCreate" => { @@ -522,6 +652,7 @@ def queries "id" => "gid://shopify/WebhookSubscription/12345", "includeFields" => ["field1", "field2"], "metafieldNamespaces" => ["namespace1", "namespace2"], + "filter" => "id:*", }, }, }, @@ -548,6 +679,17 @@ def queries }, }, }, + register_add_with_filter_response: { + "data" => { + "pubSubWebhookSubscriptionCreate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter": "id:*", + }, + }, + }, + }, check_existing_response: { "data" => { "webhookSubscriptions" => { @@ -577,6 +719,7 @@ def queries }, "includeFields" => ["field1", "field2"], "metafieldNamespaces" => ["namespace1", "namespace2"], + "filter" => "id:*", }, ], }, @@ -626,7 +769,21 @@ def queries } } QUERY - + register_update_query_with_filter: + <<~QUERY, + mutation webhookSubscription { + pubSubWebhookSubscriptionUpdate(id: "gid://shopify/WebhookSubscription/12345", webhookSubscription: {pubSubProject: "my-project-id", pubSubTopic: "my-topic-id", filter: "id:*"}) { + userErrors { + field + message + } + webhookSubscription { + id + filter + } + } + } + QUERY register_update_response: { "data" => { "pubSubWebhookSubscriptionUpdate" => { @@ -657,6 +814,17 @@ def queries }, }, }, + register_update_with_filter_response: { + "data" => { + "pubSubWebhookSubscriptionUpdate" => { + "userErrors" => [], + "webhookSubscription" => { + "id" => "gid://shopify/WebhookSubscription/12345", + "filter" => "id:*", + }, + }, + }, + }, }, fetch_id_query: <<~QUERY,