/// <summary>
        /// Allows you to continuously make a root query, till the response is deemed ready.
        /// </summary>
        /// <param name="isReady">A <see cref="Delegates.PollUpdatedHandler"/> that determines if polling should stop by returning true</param>
        /// <param name="query">The query to be queried continuously</param>
        /// \code
        /// // Example that uses polling
        /// QueryRootQuery query = new QueryRootQuery();
        ///
        /// query.node(
        ///     buildQuery: node => node
        ///         .onCheckout(checkout => checkout.ready()),
        ///     id: "someCheckoutID""
        /// );
        ///
        /// PollUpdatedHandler isReadyHandler = (updatedQueryRoot) => {
        ///     var expectedNode = (Checkout) updatedQueryRoot.node();
        ///     return expectedNode.ready();
        /// };
        ///
        /// PollQuery(isReadyHandler, query, (response, error) => {
        ///     if (error == null) {
        ///         var checkout = (Checkout) response.node();
        ///         // checkout.ready() is true
        ///     }
        ///})
        public void PollQuery(PollUpdatedHandler isReady, QueryRootQuery query, QueryRootHandler callback)
        {
            const float POLL_DELAY_SECONDS = 0.5f;

            Query(query, (QueryRoot response, ShopifyError error) => {
                if (error != null)
                {
                    callback(response, error);
                }
                else
                {
                    if (isReady(response))
                    {
                        callback(response, null);
                    }
                    else
                    {
#if !SHOPIFY_MONO_UNIT_TEST
                        UnityTimeout.Start(POLL_DELAY_SECONDS, () => {
                            PollQuery(isReady, query, callback);
                        });
#else
                        PollQuery(isReady, query, callback);
#endif
                    }
                }
            });
        }
        /// <summary>
        /// Allows you to build and send custom GraphQL queries to the Storefront API. While having utility functions like <see ref="ShopifyClient.products">products </see>
        /// <see ref="ShopifyClient.collections">collections </see> is useful, the Storefront API has more functionality. This method
        /// allows you to access all the extra functionality that the Storefront API provides.
        /// </summary>
        /// <param name="buildQuery">
        /// delegate that will build a query starting at <see ref="QueryRootQuery">QueryRootQuery </see>
        /// which will be sent to the Storefront API
        /// </param>
        /// <param name="callback">callback which will receive a response</param>
        /// \code
        /// // Example that builds a query that queries a Shop's name
        /// ShopifyBuy.Client().Query(
        ///     query: q => q
        ///         .shop(s => s
        ///             .name()
        ///         ),
        ///     callback: (data, error) => {
        ///         if (error != null) {
        ///             Debug.Log("There was an error: " + error.Reason);
        ///         } else {
        ///             Debug.Log(data.shop().name());
        ///         }
        ///     }
        /// );
        /// \endcode
        public void Query(QueryRootDelegate buildQuery, QueryRootHandler callback)
        {
            QueryRootQuery query = new QueryRootQuery();

            buildQuery(query);

            Query(query, callback);
        }
 /// <summary>
 /// Allows you to send custom GraphQL queries to the Storefront API. While having utility functions like <see ref="ShopifyClient.products">products </see>
 /// <see ref="ShopifyClient.collections">collections </see> is useful, the Storefront API has more functionality. This method
 /// allows you to access all the extra functionality that the Storefront API provides.
 /// </summary>
 /// <param name="query">a GraphQL query to be sent to the Storefront API</param>
 /// <param name="callback">callback which will receive a response from the query</param>
 /// \code
 /// // Example that queries a Shop's name
 /// QueryRoot query = new QueryRootQuery();
 ///
 /// query.shop(s => s
 ///     .name()
 /// );
 ///
 /// ShopifyBuy.Client().Query(
 ///     query: query,
 ///     callback: (data, error) => {
 ///         if (error != null) {
 ///             Debug.Log("There was an error: " + error.Reason);
 ///         } else {
 ///             Debug.Log(data.shop().name());
 ///         }
 ///     }
 /// );
 /// \endcode
 public void Query(QueryRootQuery query, QueryRootHandler callback)
 {
     Loader.Query(query, (response) => {
         callback(response.data, (ShopifyError)response);
     });
 }