Improving route handler
Answered
Holland Lop posted this in #help-forum
Holland LopOP
im working with Shopify's storefront API, and I'm using the shopify-buy SDK. I'm also using nextjs. I wanted to create a route handler (an api route on the site) to fetch products from the shopify store, so I have this:
the problem is that the fetchAll() function doesn't include tags, so I had to make a second request to get those. Is there a way to improve this code? Or an easier way? should I ditch this SDK all together? thanks
const client = Client.buildClient({
domain: process.env.SHOPIFY_DOMAIN!,
storefrontAccessToken: process.env.SHOPIFY_STOREFRONT_TOKEN!,
apiVersion: process.env.SHOPIFY_API_VERSION!,
});
const data = await client.product.fetchAll();
// this is some of the most sketch shit i have ever done.
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection(
'products',
{ args: { first: 10 } },
(product: any) => {
product.add('id');
product.add('tags');
}
);
});
const tags = await client.graphQLClient.send(productsQuery);
tags.model.products.forEach((x: any) => {
data.map((d: any) => {
// set the tags of the product
if (d.id === x.id) {
let ts = x.tags.map((t: any) => t.value);
d.tags = ts;
}
return d;
});
});
// Create a new Response with the data and set Cache-Control to disable caching
const response = new Response(JSON.stringify(data));
// .model.products
return response;the problem is that the fetchAll() function doesn't include tags, so I had to make a second request to get those. Is there a way to improve this code? Or an easier way? should I ditch this SDK all together? thanks
Answered by Ray
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection("products", { args: { first: 10 } }, (product: any) => {
product.add("id");
product.add("tags");
product.addConnection(
"variants",
{ args: { first: 20 } },
(variants: any) => {
variants.add("id");
variants.add("title");
variants.add("price", (price) => {
price.add("amount");
price.add("currencyCode");
});
}
);
});
});does this work?
46 Replies
@Holland Lop im working with Shopify's storefront API, and I'm using the shopify-buy SDK. I'm also using nextjs. I wanted to create a route handler (an api route on the site) to fetch products from the shopify store, so I have this:
ts
const client = Client.buildClient({
domain: process.env.SHOPIFY_DOMAIN!,
storefrontAccessToken: process.env.SHOPIFY_STOREFRONT_TOKEN!,
apiVersion: process.env.SHOPIFY_API_VERSION!,
});
const data = await client.product.fetchAll();
// this is some of the most sketch shit i have ever done.
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection(
'products',
{ args: { first: 10 } },
(product: any) => {
product.add('id');
product.add('tags');
}
);
});
const tags = await client.graphQLClient.send(productsQuery);
tags.model.products.forEach((x: any) => {
data.map((d: any) => {
// set the tags of the product
if (d.id === x.id) {
let ts = x.tags.map((t: any) => t.value);
d.tags = ts;
}
return d;
});
});
// Create a new Response with the data and set Cache-Control to disable caching
const response = new Response(JSON.stringify(data));
// .model.products
return response;
the problem is that the fetchAll() function doesn't include tags, so I had to make a second request to get those. Is there a way to improve this code? Or an easier way? should I ditch this SDK all together? thanks
I think you can use route segment config?
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
and you can just
return Response.json(data)also, i was trying to disable caching by just initializing a dummy variable to the request headers. would that be the correct way to do it?
what do you want to achieve?
Holland LopOP
well, i want to create an API route that returns shopify products from a store (given the proper permissions) with their tags.
since an access token is needed to do this i decided to create an API route instead of just fetching data straight from a component.
i was mainly asking about including product tags with the product data, but i’ll probably just open an issue on the shopify-buy package because it’s more relevant there.
since an access token is needed to do this i decided to create an API route instead of just fetching data straight from a component.
i was mainly asking about including product tags with the product data, but i’ll probably just open an issue on the shopify-buy package because it’s more relevant there.
hopefully that helps
this is part of a custom storefront, so i’m not trying to scrape other shopify stores or anything
the
productsQuery doesn't return the product data?I think you can get more data with this?
product.add('id');
product.add('tags');
product.add('title');
product.add('more field');@Ray I think you can get more data with this?
ts
product.add('id');
product.add('tags');
product.add('title');
product.add('more field');
Holland LopOP
most definitely. i only used the solution above as a quick prototype. the issue is that i was struggling to find any documentation on this approach. simply taking object fields from the results of fetchAll and adding them, for example, “variantsâ€, didn’t work.
that’s why i said i probably should just open an issue on the package because this question isn’t relevant here
oh maybe take a look of this example from vercel, they use shopify too but without the sdk. just graphql
https://github.com/vercel/commerce
https://github.com/vercel/commerce
@Ray oh maybe take a look of this example from vercel, they use shopify too but without the sdk. just graphql
https://github.com/vercel/commerce
Holland LopOP
ah ok, i’ll take a look. the SDK has been really frustrating so i’m thinking of alternatives.
does
product.addConnection('variants') work?i think it should work that way
@Ray does `product.addConnection('variants')` work?
Holland LopOP
i didn’t try that actually, only
products.add(“variantsâ€)I think you need
addConnection@Ray i think it should work that way
Holland LopOP
oh? i’ll try it
variants is connection
Holland LopOP
ahh i see
this is my first time using graphQL as well, so i’m a little overwhelmed in general haha
@Ray from the fragment on vercel exxample
Holland LopOP
i’m going to take a look at the vercel example and stick with the SDK, because i believe the SDK is intended to build queries like this
yes it should be
product.addConnection('variants')try it and let me know
I have never use the sdk before so Im not sure
Holland LopOP
alright, i’ll give it a shot. thank you so much for the help you’ve provided, i really appreciate it
Holland LopOP
so, simply doing something like this:
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection(
'products',
{ args: { first: 10 } },
(product: any) => {
product.add('id');
product.add('tags');
product.addConnection('variants');
}
);
}); doesn't work and throws the error: TypeError: Cannot read properties of undefined (reading 'products')im looking at the vercel commerce example and i like it a lot though
@Holland Lop so, simply doing something like this:
ts
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection(
'products',
{ args: { first: 10 } },
(product: any) => {
product.add('id');
product.add('tags');
product.addConnection('variants');
}
);
});
doesn't work and throws the error: `TypeError: Cannot read properties of undefined (reading 'products')`
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection("products", { args: { first: 10 } }, (product: any) => {
product.add("id");
product.add("tags");
product.addConnection(
"variants",
{ args: { first: 20 } },
(variants: any) => {
variants.add("id");
variants.add("title");
variants.add("price", (price) => {
price.add("amount");
price.add("currencyCode");
});
}
);
});
});does this work?
Answer
my next issue is that graphQL queries like this can only be made through the unoptimized client, which doesn't have a typescript declaration..?
Could not find a declaration file for module 'shopify-buy/index.unoptimized.umd'.So, is there a way to have type safety when making queries this way?
@Ray ts
const productsQuery = client.graphQLClient.query((root: any) => {
root.addConnection("products", { args: { first: 10 } }, (product: any) => {
product.add("id");
product.add("tags");
product.addConnection(
"variants",
{ args: { first: 20 } },
(variants: any) => {
variants.add("id");
variants.add("title");
variants.add("price", (price) => {
price.add("amount");
price.add("currencyCode");
});
}
);
});
});
does this work?
Holland LopOP
and, i think i'm starting to understand graphQL a little more through this example. it makes sense a little more
could I ask how you figured this out though, so I could do the rest myself?
@Holland Lop could I ask how you figured this out though, so I could do the rest myself?
from the product fragment and the example on their readme
@Ray what query cause this error?
Holland LopOP
just importing the unoptimized client caused it
ahh what is it for?
Holland LopOP
with this SDK, in order to build queries like you showed, and in my case in order to get the tags of products, you have to import from the unoptimized client.
similarly, i would probably have to open an issue about this to get type support/safety on the unoptimized shopify client
yeah
Holland LopOP
alright for now, i’ll mark this as solved
@Ray yeah
Holland LopOP
thank you so much for the help
np