A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
I've created a React/Node Shopify app via Shopify CLI
With the tutorials, I can query data and mutate data with GraphQL
But I want to query "pages" which only available with RestAPI
Anyone having example Call Rest API with Shopify CLI ?
Below are my shopify CLI config for GraphQL and how I using GraphQL to query data
import { Shopify } from "@shopify/shopify-api";
const TEST_GRAPHQL_QUERY = `
{
shop {
name
}
}`;
export default function verifyRequest(app, { returnHeader = true } = {}) {
return async (req, res, next) => {
const session = await Shopify.Utils.loadCurrentSession(
req,
res,
app.get("use-online-tokens")
);
let shop = req.query.shop;
if (session && shop && session.shop !== shop) {
// The current request is for a different shop. Redirect gracefully.
return res.redirect(`/auth?shop=${shop}`);
}
if (session?.isActive()) {
try {
// make a request to make sure oauth has succeeded, retry otherwise
const client = new Shopify.Clients.Graphql(
session.shop,
session.accessToken
);
await client.query({ data: TEST_GRAPHQL_QUERY });
return next();
} catch (e) {
if (
e instanceof Shopify.Errors.HttpResponseError &&
e.response.code === 401
) {
// We only want to catch 401s here, anything else should bubble up
} else {
throw e;
}
}
}
if (returnHeader) {
if (!shop) {
if (session) {
shop = session.shop;
} else if (Shopify.Context.IS_EMBEDDED_APP) {
const authHeader = req.headers.authorization;
const matches = authHeader?.match(/Bearer (.*)/);
if (matches) {
const payload = Shopify.Utils.decodeSessionToken(matches[1]);
shop = payload.dest.replace("https://", "");
}
}
}
if (!shop || shop === "") {
return res
.status(400)
.send(
`Could not find a shop to authenticate with. Make sure you are making your XHR request with App Bridge's authenticatedFetch method.`
);
}
res.status(403);
res.header("X-Shopify-API-Request-Failure-Reauthorize", "1");
res.header(
"X-Shopify-API-Request-Failure-Reauthorize-Url",
`/auth?shop=${shop}`
);
res.end();
} else {
res.redirect(`/auth?shop=${shop}`);
}
};
}
import { gql, useQuery } from "@apollo/client";
import { Page, Layout, Banner, Card } from "@shopify/polaris";
import { Loading } from "@shopify/app-bridge-react";
import { ProductsList } from "./ProductsList";
// GraphQL query to retrieve products by IDs.
// The price field belongs to the variants object because
// product variants can have different prices.
const GET_PRODUCTS_BY_ID = gql`
query getProducts($ids: [ID!]!) {
nodes(ids: $ids) {
... on Product {
title
handle
descriptionHtml
id
images(first: 1) {
edges {
node {
id
originalSrc
altText
}
}
}
variants(first: 1) {
edges {
node {
price
id
}
}
}
}
}
}
`;
export function ProductsPage({ productIds }) {
const { loading, error, data, refetch } = useQuery(GET_PRODUCTS_BY_ID, {
variables: { ids: productIds },
});
if (loading) return <Loading />;
if (error) {
console.warn(error);
return (
<Banner status="critical">There was an issue loading products.</Banner>
);
}
return (
<Page>
<Layout>
<Layout.Section>
<Card>
<ProductsList data={data} />
</Card>
</Layout.Section>
</Layout>
</Page>
);
}