Gatsby GraphQL not getting images data from Strapi - image

I'm using Strapi v.4 and Gatsby v.4.23.0
I use gatsby-source-strapi v.2
My gatsby-config.js looks like this
const strapiConfig = {
apiURL: process.env.STRAPI_API_URL,
accessToken: process.env.STRAPI_TOKEN,
collectionTypes: [
{
singularName: 'article',
queryParams: {
// Populate media and relations
// Make sure to not specify the fields key so the api always returns the updatedAt
populate: {
'articleSection': {
image: {
populate: {
data: "*"
}
},
images: "*",
},
'categories': "*"
},
},
},
{
singularName: 'category',
},
],
singleTypes: [],
}
In Strapi, the Article data model is like this:
When I explore Strapi GraphQL I can see images data, but the same data are not available in Gatsby GraphQL explorer. I see something like the following:
As you can see there are no images.
How can I get image data?

Solved with this config
const strapiConfig = {
apiURL: process.env.STRAPI_API_URL,
accessToken: process.env.STRAPI_TOKEN,
collectionTypes: [
{
singularName: 'article',
queryParams: {
// Populate media and relations
// Make sure to not specify the fields key so the api always returns the updatedAt
populate: {
'articleSection': {
populate: "*"
},
'categories': "*"
},
},
},
{
singularName: 'category',
},
],
singleTypes: [],
}

Related

How to access a Strapi custom GraphQL query in Gatsby's data layer?

I'm making a blog using Gatsby v4.4.0 as the frontend and Strapi v4.4.5 as the backend/CMS, and want to be able to query articles by random (for example, get 3 random articles). I created a custom GraphQL query by extending Strapi's GraphQL schema (following this article and the Strapi docs on GraphQL) for this purpose.
The query resolver in Strapi - src/api/article/graphql.js:
"use strict";
module.exports =
(strapi) =>
({ nexus }) => ({
typeDefs: `
type RandomArticleResponse {
data: [ArticleEntity]!
}
extend type Query {
randomArticle(limit: Int, exclude: ID): RandomArticleResponse
}
`,
resolvers: {
Query: {
randomArticle: {
resolve: async (parent, args, context) => {
const DEFAULT_LIMIT = 3;
const limit = args.limit || DEFAULT_LIMIT;
const excludedIds = args.exclude ? [args.exclude] : [];
const ids = (
await strapi.db.connection
.select("id")
.from("articles")
.whereNotIn("id", excludedIds)
.orderByRaw("RANDOM()")
.limit(limit)
).map((it) => it.id);
const data = await strapi.entityService.findMany(
"api::article.article",
{
filters: {
id: {
$in: ids,
},
},
}
);
return { data };
},
},
},
},
});
This part works fine and I can query from Strapi's GraphQL playground (image), but to be able to be used in Gatsby the query has to be accessible from Gatsby's GraphQL Data Layer, which it seemingly isn't by default since the query isn't showing up in GraphiQL (image).
I am using gatsby-source-strapi for pulling documents into Gatsby from the Strapi API. My options in gatsby-config.js are:
{
resolve: `gatsby-source-strapi`,
options: {
apiURL: process.env.STRAPI_API_URL || "http://localhost:8082",
accessToken: process.env.STRAPI_TOKEN,
collectionTypes: [
{
singularName: "article",
queryParams: {
publicationState:
process.env.GATSBY_IS_PREVIEW === "true" ? "preview" : "live",
populate: {
cover: "*",
column: "*",
tags: "*",
blocks: {
populate: "*",
},
author: "*",
references: "*",
},
},
},
{
singularName: "author",
},
{
singularName: "column",
queryParams: {
populate: {
articles: "*",
},
},
},
{
singularName: "tag",
queryParams: {
populate: {
articles: "*",
},
},
},
],
singleTypes: [
{
singularName: "about",
queryParams: {
populate: {
author: "*",
blocks: "*",
},
},
},
{
singularName: "global",
queryParams: {
populate: {
favicon: "*",
defaultSeo: "*",
},
},
},
],
},
}
I think I have to add randomArticles to a data source plugin somehow but I'm not sure how to do that. I've tried reading gatsby-source-strapi docs and the docs about Source Plugins but I'm not sure which parts are relevant to this problem. Has anyone had issues with this same use case? Any advice would be appreciated. Thanks!

Cannot query field "allDevArticles" on type "Query" graphql/template-strings for fetching dev.to articles

I am using the gatsby-source-dev gatsby plugin to get all my dev.to articles on my gatsby page.
https://github.com/geocine/gatsby-source-dev
It was working fine but recently it started giving me this error.
"cannot query field "allDevArticles" on type "Query" graphql/template-strings"
and not able to fetch my latest articles on the site.
My gatsby-config.js looks like this
module.exports = {
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `profile`,
path: `./data`,
},
},
`gatsby-transformer-sharp`,
`gatsby-transformer-json`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-source-dev`,
options: {
username:'vish448'
}
},
],
}
My graphql query on the page looks like this
export const query = graphql`
query ArticlePageQuery {
allDevArticles {
nodes {
article {
title
url
published_at(formatString: "DD MMM YYYY")
}
}
}
}`
I have updated my configuration in gatsby-config.js for gatsby-source-dev plugin and it works fine. So basically those string quotes are causing an issue. I have changed those quotes to string literals (``)
module.exports = {
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `profile`,
path: `./data`,
},
},
`gatsby-transformer-sharp`,
`gatsby-transformer-json`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-source-dev`,
options: {
**username:`vish448`**
}
},
],
}

How to explicitly set schema field type to [SanityImage]

I want to set an images field in my document to an array of type [SanityImage].
I have tried setting it to type: 'image' but when I query the field I get that the type is [SanityCollectionItemsImages]
The images field is found inside an object (productVariant) which is then included in the main document (collection) where I have an array of productVariants in my items field.
Inside the fields array of my collection document:
...
{
title: "Items",
name: "items",
type: "array",
of: [
{
title: "Item",
type: "productVariant",
},
],
},
...
The productVariant type object:
export default {
title: "Product variant",
name: "productVariant",
type: "object",
fields: [
{
name: "images",
title: "Images",
type: "array",
of: [
{
type: "image",
options: {
hotspot: true,
},
},
],
},
...
My query using GraphQL:
allSanityCollection {
edges {
node {
_id
title
description
items {
_key
title
images {
asset {
_ref
_id
fluid(maxHeight: 600) {
base64
aspectRatio
src
srcSet
srcWebp
srcSetWebp
sizes
}
}
}
}
}
}
}
When I click on the the images field inside the GraphiQL web IDE:
Using Sanity.io HTTP API to get the whole document:
"images": [
{
"_key": "5605f5383975",
"_type": "image",
"asset": {
"_ref": "image-14f9b7688912499f187b7c20e57816b3cdf42c1e-4016x4688-jpg",
"_type": "reference"
}
},
...
My question is how to set the type of a field in my schema to be explicitly [SanityImage] instead of [SanityCollectionItemsImages] and why do I get that weird type?
The Sanity schema looks totally sane, and the API delivers the proper data structure as you say, so the problem seems to be related to the Gatsby and GraphQL layer of things.
I'll recommend making sure you are using the latest versions of the CLI, Studio and Sanity Gatsby plugin and see if that makes things better as development on the Gatsby source plugin is moving fast.

mapper_parsing_exception while updating a document in elastic search using javascript client

I fetch a document from ES and then try to update it using js client:
Structure of document is as(partial):
{
_id = "2c3cb61e-fd2a-11e8-8ac1-0242ac110008",
_index = "my_index",
_source: {taskName: "Task_name",....}
}
Code:
hit._source.taskName = 'New_task_name';
esClient.bulk({
body: [
{ update: { _index: 'my_index', _type: 'default', _id: hit._id }},
{ doc: hit}
]
}, function (err, resp) {
// ...
console.log(err, resp);
});
But it gives error as:
{ "type": "mapper_parsing_exception", "reason": "Field [_index] is
a metadata field and cannot be added inside a document. Use the index
API request parameters." }
Does it mean I can't have _index as field name in my document?
Great job so far, you're almost there!! You only need to send what's in the _source, do it like this instead:
hit._source.taskName = 'New_task_name';
esClient.bulk({
body: [
{ update: { _index: 'my_index', _type: 'default', _id: hit._id }},
{ doc: hit._source} <-- change here
]
}, function (err, resp) {
// ...
console.log(err, resp);
});

apollo-link-state add field with default value to type

Here's what I'm trying to accomplish:
I have a graphql API endpoint that returns me a Project object like this(unrelated fields removed):
{
"data": {
"Project": {
"id": "cjp4b84wkochq0167gpu8oa7h",
"requests": [
{
"id": "cjpbb6jcdpwj00167y4acl5a1",
"__typename": "Request"
},
{
"id": "cjpbbhlaxpwlx01675jzfyb0j",
"__typename": "Request"
},
{
"id": "cjpbbifg7pwmg0167s0ob1bm6",
"__typename": "Request"
},
],
"__typename": "Project"
}
}
}
I want to use apollo-link-state to add a client-side field to all of these Request objects like this:
{
"data": {
"Project": {
"id": "cjp4b84wkochq0167gpu8oa7h",
"requests": [
{
"id": "cjpbb6jcdpwj00167y4acl5a1",
"expanded": false,
"__typename": "Request"
},
{
"id": "cjpbbhlaxpwlx01675jzfyb0j",
"expanded": false,
"__typename": "Request"
},
{
"id": "cjpbbifg7pwmg0167s0ob1bm6",
"expanded": false,
"__typename": "Request"
},
],
"__typename": "Project"
}
}
}
This would allow me to remove local state from my Component that renders these requests. The problem is that when I define defaults for my ApolloClient clientState as follows:
const client = new ApolloClient({
clientState: {
defaults: {
Project: {
__typename: 'Project',
requests: [{ __typename: 'Request', expanded: false }],
},
},
},
});
Apollo adds it as a new Project object instead of adding it to the existing one(which has an id):
ROOT_QUERY
Project: Project
requests: [Request]
0:
expanded: false
Project({"id":"cjp4b84wkochq0167gpu8oa7h"}): Project
▾Project:cjp4b84wkochq0167gpu8oa7h
when I give it the id it adds the "hi" field to the correct project but the requests are still missing the expanded field. And giving the id only works for a specific project obviously.
const client = new ApolloClient({
clientState: {
defaults: {
'Project({"id":"cjp4b84wkochq0167gpu8oa7h"})': {
__typename: 'Project',
hi: true,
requests: [{ __typename: 'Request', expanded: false }],
},
},
},
});
ROOT_QUERY
Project({"id":"cjp4b84wkochq0167gpu8oa7h"}): Project
▾Project:cjp4b84wkochq0167gpu8oa7h
hi: true
requests: [Request]
0:▾Request:cjpbb6jcdpwj00167y4acl5a1
...unrelated fields
1:▾Request:cjpbbhlaxpwlx01675jzfyb0j
2:▾Request:cjpbbifg7pwmg0167s0ob1bm6
I also tried using the typeDefs field on the clientState object like this:
typeDefs: [`
schema {
query: RootQuery
}
type RootQuery {
Project($id: ID): Project
}
type Project {
id: ID!
requests: [Request]
}
type Request {
id: ID!
expanded: Boolean
}
`],
but this doesn't seem to change anything on the cache and I don't know if I can even give it a default value like this.
Maybe I'm misunderstanding how apollo-link-state works (or even how graphql works) any answer to point me in the right direction is appreciated. I'm very much a beginner when it comes to graphql or apollo.
You need to provide a client side resolver to your clientState configuration.
const clientState = {
resolvers: {
Project {
expanded: () => false
}
}
}
And then you'd pass this into your ApolloClient like so
const apolloClient = new ApolloClient({ clientState });

Resources