Creating the next custom GraphQL mutation in KeystoneJS and integrating it with an external frontend

Hello, I am currently working on setting up a custom mutation in keystone-next with an "external" react, next & apollo frontend. However, I am encountering issues when calling the mutation from the frontend, even though it works fine when called from the Keystone api explorer. The mutation itself is quite simple.

Here is the schema extension:

export const extendedGqlSchema = graphQLSchemaExtension({
  typeDefs: graphql`
    type Mutation {
      testAvailability(name: String): String
    }
  `,
  resolvers: {
    Mutation: {
      testAvailability: testAvailability,
    },
  },
});

The resolver function (in a different file) looks like this:

export const testAvailability = (
  root: any, 
  { name }: { name: string },
  context: KeystoneContext
): string => {
  if (context) {
    return new Date().toUTCString() + ": Hi " + name + ", I'm here!";
  }
  return new Date().toUTCString() + ": No context";
};

The raw http request body that works is as follows:

{
    "operationName": null,
    "variables": {},
    "query": "mutation {\n  testAvailability(name: \"Eve\")\n}\n"
}

On the other hand, the raw http frontend generated request body looks like this:

{
    "operationName": "testAvailability",
    "variables": {
        "name": "Eve"
    },
    "query": "mutation testAvailability($name: String) {\n  testAvailability(name: $name) {\n    name\n    __typename\n  }\n}\n"
}

When running these requests from Postman with the exact same headers, the first one still works while the second does not (authentication etc. may be a factor). The error received in the 400 bad request response is:

{
    "errors": [
        {
            "message": "Cannot assign to read only property 'path' of object '#<Object>'",
            "extensions": {
                "code": "INTERNAL_SERVER_ERROR",
                "exception": {
                    "stacktrace": [
                        "TypeError: Cannot assign to read only property 'path' of object '#<Object>'",
                        "    at formatError (%ProjectPath%\backend\node_modules\@keystone-next\keystone\dist\createApolloServer-231615cf.cjs.dev.js:82:24)",
                        "    at %ProjectPath%\\backend\\node_modules\\apollo-server-errors\\src\\index.ts:287:28",
                        "    at Array.map (<anonymous>)",
                        "    at Object.formatApolloErrors (%ProjectPath%\\backend\\node_modules\\apollo-server-errors\\src\\index.ts:285:25)",
                        "    at formatErrors (%ProjectPath%\\backend\\node_modules\\apollo-server-core\\src\\requestPipeline.ts:665:12)",
                        "    at %ProjectPath%\\backend\\node_modules\\apollo-server-core\\src\\requestPipeline.ts:649:15",
                        "    at Generator.next (<anonymous>)",
                        "    at fulfilled (%ProjectPath%\\backend\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:5:58)",
                        "    at runMicrotasks (<anonymous>)",
                        "    at processTicksAndRejections (internal/process/task_queues.js:93:5)"
                    ]
                }
            }
        }
    ]
}

I'm trying to figure out what might be missing or causing this issue. Any insights would be appreciated!

Answer №1

Upon reviewing the second query sent from the frontend, it appears to be structured as follows:

mutation testAvailability($name: String) {
  testAvailability(name: $name) {
    name
    __typename
  }
}

However, the function testAvailability actually returns a String, rather than an object. A more accurate query would resemble this:

mutation testAvailability($name: String) {
  testAvailability(name: $name)
}

Therefore, it is advisable to double-check the structure of your frontend query.

Regarding the unexpected error message stating "Cannot assign to read only property 'path' of object '#<Object>'", its origin remains unclear to me. When attempting to reproduce the issue, I encountered a GRAPHQL_VALIDATION_FAILED error instead:

Field "testAvailability" must not have a selection since type "String" has no subfields.

This error message provides much more insightful information in troubleshooting the problem!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on converting any object with keys of type string to a generic type

I'm grappling with a function that yields an Output generic type. In this function, I initiate an API request that responds with a json object. My aim is to have the function return this json object in the Output Generic type format Take a look at th ...

Storing data from a collection of interface objects in a string array

Take a look at the following code snippet: import React, {FC} from 'react'; import {useFetchErrors} from "../Api/Api"; import {useLocation} from "react-router-dom"; interface ExecutionTableProps { project_id: number } const ...

Utilizing Angular 5: Display a Loading Indicator while Searching using Async Pipe

As I work on incorporating a search field with async in Angular 5, I want the loading indicator to appear when the user starts typing in the search box and disappear once the results are fetched. However, following this approach led to the loading indicato ...

What is the best way to declare strings within a Typescript interface?

I have an array of Projects with multiple strings in the stack property const projects: IProject[] = [ {name: '', description: '', stack: {'php', 'sql'}} ] What is the best approach for defining the interface? ...

Establish a starting point in react-draft-wysiwyg and modify the state when there are changes in the props

When receiving rawData as props in an HTML form, the process begins with the convertFromHTML function and then creating an instance of EditorState. Everything works smoothly when navigating from /article/:articleId to /article/:articleId/edit. However, if ...

The Concept of Static Block in TypeScript

For the purpose of testing Network Encoding/Decoding Logic, I have implemented a pair of test cases in both Java and JavaScript. These tests utilize Data Providers which essentially consist of various Constants. In my Java test case, I have a Data Provide ...

Getting the hang of using and translating typescript .tsx files with jsx in React-native

Recently, I have ventured into the world of React-native after having experience with reactjs+typescript. Wanting to test its capabilities, I decided to set up a simple project. My tool of choice for development is VS Code. After following a basic tutoria ...

Is it possible to modify a portion of the zod schema object according to the value of a

My form consists of several fields and a switch component that toggles the visibility of certain parts of the form, as shown below: <Field name="field1" value={value1} /> <Field name="field2" value={value2} /> &l ...

Async/Await function is not behaving as intended

Our current approach involves storing short strings as keys. These keys are linked to longer values, which serve as labels. I am attempting to update the corresponding longer value for each key. However, a problem arises where console.log(record) always ...

The index expression is not of type 'number', which is why it is implicitly classified as an 'any' type in this scenario

Utilizing the Zxing Scanner component within Angular version 12 has led me to encounter this particular error on multiple occasions. /** * Returns a valid BarcodeFormat or fails. */ private getBarcodeFormat(format: string | BarcodeFormat): BarcodeFormat ...

Why are certain typescript 3.7 features not accessible when targeting ESNext?

Currently, I am utilizing bigint literals within my Angular project which are only available in ESNext. However, it seems that the null-coalescing operator mentioned here is not accessible when targeting ESNext. this._id = id ?? Util.makeGuid() This line ...

Exploring the Depths of Angular 11's Named Nested Router Outlets

I am facing an issue with my router configuration. Here is the current setup: const appRoutes: Routes = [ { path: '', component: LoginComponent}, { path: 'login', component: LoginComponent }, { path: 'main', component: M ...

What are some effective methods for bypassing pop-up blockers in Angular 6?

I need to display a PDF when the preview button is clicked, however the PDF is blocked from opening in a new tab. I am looking for a way to bypass the pop-up blocker settings of browsers. getPdf(projectId) { this.http.get(environment.apiUrl + "/poject/g ...

Utilizing the Solana Wallet Key for ArweaveJS Transaction Signing

Is there a method to import a Solana wallet keypair into the JWKInterface according to the node_modules/arweave/node/lib/wallet.d.ts, and then generate an Arweave transaction using await arweave.createTransaction({ data }, jwk);? Metaplex utilizes an API ...

Angular Universal build stuck on rendering page while waiting for API response

I'm currently developing a compact web application using the angular universal starter in combination with pokeapi. To enhance performance and reduce API requests, I intend to implement pre-rendered pages since the data displayed remains mostly static ...

Creating an interface in Dart: Step-by-step guide to defining interfaces similar to TypeScript

Coming from a Typescript background, I used to define object interfaces like this: export interface Locale { login: { title: string; actions: { submit: string; forgot: string; } } } However, in Dart, interfaces are implicit an ...

Union types can be used to constrain generic type parameters in Typescript

I'm working on a function uniqueIds(first: any[], second: any[]): number[] { let prop = first[0] instanceof Owner ? "OwnerId" : "BankId"; return _.unique( _.map( first, o => ...

What could be causing the "serviceName error: No provider found" message to appear?

Currently, I am working on sharing a value between two components in Angular. The setup involves a ProjectView component that renders a ProjectViewBudget component as a "child" (created within a dynamic tab component using ComponentFactoryResolver) with th ...

What is the process for integrating Typescript into a Quasar 2 project that is utilizing Vite as its build tool?

The Quasar 2 documentation provides in-depth guidance on integrating Typescript with Webpack: Unfortunately, my Quasar project is configured with Vite and I am struggling to locate resources on incorporating Typescript into an already existing project. A ...

Error: The phone number provided for SNS.optInPhoneNumber is invalid

I'm attempting to utilize the optInPhoneNumber function in AWS SNS, but I keep encountering this error. InvalidParameter: Invalid parameter: at Request.extractError at Request.callListeners at Request.emit at Request.emit ...