I have a Graphql schema that looks like this:
type Mutation {
createUploadUrl(
input: CreateUploadUrl!
): MyResponse!
}
input CreateUploadUrl {
deploymentId: ID!
}
I'm new to Graphql and am getting lost when trying to work out what my query should look like when I submit it via fetch:
fetch('https://example.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
mutation($input: ) {
createUploadUrl($input) {
__typename,
// my values I want to retrieve
// ...
}
}`,
variables: {
input: {deploymentId: "XXX"}
}
}),
})
.then((res) => res.json())
.then((result) => console.log(result));
The above gives me an error: `message: "Syntax Error: Expected Name, found "$"."
How am I supposed to specify a query or mutation that requires an object as a variable?
`
You just need to define your parametrized function and wrap the effective mutation.
In the example below the mutation MyMutation takes as param a $arg wich is a CreateUploadUrl!.
Then pass the $arg to the input of the mutation, the invocation becomes:
mutation MyMutation($arg: CreateUploadUrl!) {
createUploadUrl(input: $arg) {
__typename,
...
}
I am working with GatsbyJS and GraphQL for the first time and trying to generate certain pages dynamically based on slug values.
Currently I am able to generate all of the relevant pages using the createPages API extension, but the pages are blank, no data is being retrieved.
I'm not quite sure how to retrieve the data from within the template. When I write the query I get errors like "GraphQLError: Syntax Error: Expected Name, found \"$\".", when adding $slug: string! for example.
Any help would be appreciated on this!
gatsby-node.js
exports.createPages = async function ({ actions, graphql }) {
const { data } = await graphql(`
query {
dataJson {
work {
slug
}
}
}
`)
data.dataJson.work.forEach(edge => {
const slug = edge.slug;
actions.createPage({
path: `work/${slug}`,
component: require.resolve(`./src/templates/work-article.tsx`),
context: { slug: slug },
})
})
}
template.js
export const query = graphql`
query($slug: String!) {
dataJson {
work(slug: $slug) {
slug
title
}
}
}
`;
gatsby-config.js
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'data', // Identifier. Will then be queried as `dataJson`
path: './src/assets/data', // Source folder containing the JSON files
},
},
Example of the data saved in data.json
{
"work": [
{
"slug": "my-slug",
"title": "My Title",
"img": "/static/img.jpg"
},
...
}
could anyone please help me understand on how to validate the input argument object type on apollo client , i am trying to make sure that passing additional fields on the input object fails the query . But it works even if i pass additional fields (Note : I want the validation on front end and not on the server)
const mutationInput = new GraphQLObjectType({
name: 'mutationInput',
fields: {
Id: String,
statusCode: String,
}
});
const GET_DATA = gql`
mutation($in: ${mutationInput}!){
getData(in: $in) {
status
}
}
}`;
//usage
const [getData, { error,loading }] = useMutation(
GET_DATA,
{
...
}
)
getData({
variables: {
in: {
statusCode:"OK",
ID:"azz12",
extraField:"some value" //Validation needs to fail as this field is not defined on input object, but never fails on front end
}
}
I am using graphql to get some data.
let { loading, error, data } = useQuery(GET_JOBS_SEARCH, {
variables: {
category: category,
type: jobType
}
});
Now when I update the category the API gets called with variables like
variables: {category: "leadership", type: ""}
Now I don't want the type:'' in my call.
I've been trying to research on how to add another root property of a GraphQL response but found nothing after 1 hour.
Normally, a GraphQL query looks like this:
{
myQuery() {
name
}
}
It responds with:
{
"data": {
"myQuery": []
}
}
I'm curious if I can add another root property in this response say "meta"
{
"data": {
"myQuery": []
},
"meta": {
"page": 1,
"count": 10,
"totalItems": 90
}
}
Is this possible, if not what's the best approach in tackling this with respect to GraphQL?
Thanks!
The apollo-server middleware can be configured with a number of configuration options, including a formatResponse function that allows you to modify the outgoing GraphQL response
const formatResponse = (response) => {
return {
meta
...response
}
}
app.use('/graphql', bodyParser.json(), graphqlExpress({
schema,
formatResponse,
}));
You could pass the req object down to your context, mutate it within your resolver(s) and then use the result inside formatResponse. Something like...
app.use('/graphql', bodyParser.json(), (req, res, next) => graphqlExpress({
schema,
formatResponse: (gqlResponse) => ({
...gqlResponse
meta: req.metadata
}),
})(req, res, next));
Typically, though, you would want to include the metadata as part of your actual schema and have it included with the data. That will also allow you to potentially request multiple queries and get the metadata for all of them.
There's any number of ways to do that, depending on how your data is structured, but here's an example:
type Query {
getFoos: QueryResponse
getBars: QueryResponse
}
type QueryResponse {
results: [Result]
meta: MetaData
}
union Result = Bar | Foo
You can add anything in the response as well... Please follow below code.
app.use('/graphql', bodyParser.json(), graphqlExpress(req => {
return {
schema: tpSchemaNew,
context: {
dbModel
},
formatError: err => {
if (err.originalError && err.originalError.error_message) {
err.message = err.originalError.error_message;
}
return err;
},
formatResponse : res => {
res['meta'] = 'Hey';
return res;
}
}
}))
Apollo Server-specific:
Just adding to the previous answers that formatResponse() has another useful argument, requestContext.
If you are interested in extracting values from that (for example, the context passed to the resolver), you can do the following. BEWARE HOWEVER, the context will likely contain sensitive data that is supposed to be private. You may be leaking authentication data and secrets if not careful.
const server = new ApolloServer({
schema,
formatResponse: (response, requestContext) => {
//return response
const userId = requestContext.context.user.id
response = Object.assign(response, {
extensions: {
meta: {
userId: userId
}
}
}
return response
},
})
The above will return something like this in the gql query response (note the extensions object):
{
data: {
user: {
firstName: 'Hello',
lastName: 'World'
}
},
extensions: { // <= in Typescript, there is no `meta` in GraphQLResponse, but you can use extensions
meta: {
userId: 1234 //<= data from the context
}
}
}
The full list of properties available in requestContext:
at node_modules/apollo-server-types/src/index.ts>GraphQLRequestContext
export interface GraphQLRequestContext<TContext = Record<string, any>> {
readonly request: GraphQLRequest;
readonly response?: GraphQLResponse;
readonly context: TContext;
readonly cache: KeyValueCache;
// This will be replaced with the `operationID`.
readonly queryHash?: string;
readonly document?: DocumentNode;
readonly source?: string;
// `operationName` is set based on the operation AST, so it is defined even if
// no `request.operationName` was passed in. It will be set to `null` for an
// anonymous operation, or if `requestName.operationName` was passed in but
// doesn't resolve to an operation in the document.
readonly operationName?: string | null;
readonly operation?: OperationDefinitionNode;
/**
* Unformatted errors which have occurred during the request. Note that these
* are present earlier in the request pipeline and differ from **formatted**
* errors which are the result of running the user-configurable `formatError`
* transformation function over specific errors.
*/
readonly errors?: ReadonlyArray<GraphQLError>;
readonly metrics?: GraphQLRequestMetrics;
debug?: boolean;
}