React + Apollo "Getting Started" Error in Prisma Playground - reactjs

I am in the Getting Started React + Apollo chapter: https://www.howtographql.com/react-apollo/1-getting-started/
When I enter the following query in the Prisma Playground (as the tutorial tells me to do):
mutation CreatePrismaLink {
post(
description: "Prisma gives you a powerful database toolkit 😎"
url: "https://prisma.io"
) {
id
}
}
mutation CreateApolloLink {
post(
description: "The best GraphQL client for React"
url: "https://www.apollographql.com/docs/react/"
) {
id
}
}
I get this error message that I don't understand. It seems to be something about the server
"errors": [
{
"message": "Argument id for data.postedBy.connect.id must not be null. Please use undefined instead.\n",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"post"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"clientVersion": "2.12.1",
"stacktrace": [
"Error: Argument id for data.postedBy.connect.id must not be null. Please use undefined instead.",
"",
" at Document.validate (C:\\Users\\shanm\\hackernews-react-apollo\\server\\node_modules\\#prisma\\client\\runtime\\index.js:77413:19)",
" at NewPrismaClient._executeRequest (C:\\Users\\shanm\\hackernews-react-apollo\\server\\node_modules\\#prisma\\client\\runtime\\index.js:79065:17)",
" at C:\\Users\\shanm\\hackernews-react-apollo\\server\\node_modules\\#prisma\\client\\runtime\\index.js:79002:52",
" at AsyncResource.runInAsyncScope (async_hooks.js:197:9)",
" at NewPrismaClient._request (C:\\Users\\shanm\\hackernews-react-apollo\\server\\node_modules\\#prisma\\client\\runtime\\index.js:79002:25)",
" at Object.then (C:\\Users\\shanm\\hackernews-react-apollo\\server\\node_modules\\#prisma\\client\\runtime\\index.js:79119:39)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
}
}
],
"data": null
}
please help me find the problem?

This is old but in case somebody else hits this issue and Googles it like me:
Unfortunately the answer here didn't work for me, but the solution is something that was covered in the Node+GraphQL tutorial, which you might not be able to figure out on your own:
In order to post you have to first create a user and then be authorized as that user. The mutation to create a user is listed as an example on the page, but unfortunately the author forgot to instruct the reader to run it before trying to create a post.
Paste this into the playground to create a user
mutation {
signup(name: "Sarah", email: "sarah#prisma.io", password: "graphql") {
token
user {
id
}
}
}
Copy the token that is returned
Open the "HTTP Headers" pane in the bottom left
Enter this with your token:
{
"Authorization": "Bearer TOKEN_HERE"
}
Now you can run the mutations to create the posts

That's because the server has been written with the business rule in mind that a Post will always belong to a User. The database has a NOT NULL postedById field on the Link table i.e. a post will always have a user id attached to it. You need to make postedById field nullable in the Link model in the Prisma ORM schema. To fix this, make the following changes on server side code and relaunch the server
In the server folder go to schema.prisma file, and make both fields postedBy and postedById optional/nullable by suffixing them with ?
postedBy? User #relation(fields: [postedById], references:[id])
postedById? Int
Then run the following command to recreate database with the changes
npx prisma migrate reset
Update the post resolver function in Mutation.js file to replace the line
postedBy: { connect: { id: userId } }
with
postedById: userId,
because prisma connect api does not accept a null value

Related

Firebase Cloud Firestore - Fail to write via REST API

This is not an authentication error, write is enabled on the database rules.
My cloud Firestore database looks like the picture below.
There is a COLLECTION called colA, inside it there is a DOCUMENT called docA, and inside it there are some fields (strings) stored.
On Postman, if I do GET https://firestore.googleapis.com/v1/projects/eletronica-ab6b1/databases/(default)/documents/colA/docA, I do receive the following answer, and it is correct:
{
"name": "projects/eletronica-ab6b1/databases/(default)/documents/colA/docA",
"fields": {
"fieldB": {
"stringValue": "ABCD"
},
"fieldA": {
"stringValue": "888"
}
},
"createTime": "2020-01-31T16:48:26.859181Z",
"updateTime": "2020-02-05T19:21:49.654340Z"
}
Now, when I try to write a new field (fieldC) via POST https://firestore.googleapis.com/v1/projects/eletronica-ab6b1/databases/(default)/documents/colA/docA, with JSON content:
{
"name": "projects/eletronica-ab6b1/databases/(default)/documents/colA/docA",
"fields": {
"fieldC": {
"stringValue": "1000"
}
}
}
After SEND, I receive this:
{
"error": {
"code": 400,
"message": "Document parent name \"projects/eletronica-ab6b1/databases/(default)/documents/colA\" lacks \"/\" at index 60.",
"status": "INVALID_ARGUMENT"
}
}
What I'm doing wrong? I really would like to write strings there via REST API.
Regards.
Updating a document is done with a PATCH request, according to the [reference documentation).
A POST request is used to create a new document in a collection, which probably explains the error you get: you're pointing to a document, but POST expects a collection path.

Cannot read proper query in GraphQL Apollo Client

On one of my pages in my app I'm doing two api calls with graphql apollo client. One is document, the other one menu. I need menu data in one of my components so I want to use readQuery in order to not to fetch it again. What I'm doing is:
const client = useApolloClient();
try {
const testData = client.readQuery({
query: gql`
query ($result: String) {
menu(result: $result) {
text
}
}
`,
variables: {
result: „testresult”
},
});
console.log(testData);
} catch(e) {
console.log(e);
}
What graphQL is doing is looking for document root query so the error looks like this:
Invariant Violation: Can't find field menu({"lang":"en-us"}) on object
{
"document({\"lanf\":\"en-us\",\"id\":\"mySite\"})": {
"type": "id",
"generated": false,
"id": "XO5tyxAAALGzcYGG",
"typename": "Document"
}
}.
I believe that it is because menu data is not there yet.
How can I wait until it will be there?
You are right. You are getting an error because the data is not in cache yet:
The query method, on the other hand, may send a request to your server if the appropriate data is not in your cache whereas readQuery will throw an error if the data is not in your cache. readQuery will always read from the cache.
https://www.apollographql.com/docs/react/advanced/caching/#readquery
To do what you want use the a normal query with a cache-only fetchPolicy.
https://www.apollographql.com/docs/react/api/react-apollo/#optionsfetchpolicy

JS Report Server Console error: Authorization server has no "username" field in its response, token assumed as invalid

My js report server with client ui applications was working with username filed by adding one claim e.g. Claim('username', 'user name value') in identityserver.
4 version 1.1. B ut recently client has upgraded the identityserver 4 version to 2.2.0 and netcoreapp2.1 .
Now the client ui applications get "Unauthorized" error. When I run the application locally I see one error in jsreport server console:
error: Authorization server has no "username" field in its response, token assumed as invalid.
I have tried to find solution in the sample:
https://github.com/bjrmatos/jsreport-with-authorization-server-sample but they have not upgraded the sample for latest .net core and identity server yet, I see the node js sample link "https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/NodeJsApi" does not exists. so I am unable to solve the issue. Can anyone help me please on this?
Thanks in advance.
I have found solution to solve this error by adding a claim type with user name and declare that in api resource scope:
new ApiResource
{
Name="jsreportscope",
DisplayName = "JavaScript based reporting platform",
Scopes=
{
new Scope()
{
Name="jsreportscope",
UserClaims = new List<string>(){"username" }
}
},
UserClaims = new List<string>(){"username"},
ApiSecrets = { new Secret("yoursecret".Sha256()) },
}
But now it goes to the previous problem that I fixed by adding a claim type matching the value of username field value with identity server 1.1 version but now we have upgraded the identity server version to 2.1 and again getting the error. The it was able to authorize any user of identity server for report access. Here is the jsreport.config.js code I am using:
{
"store": { "provider": "fs" },
"httpPort": 5004,
"allowLocalFilesAccess": true,
"extensions": {
"authentication": {
"cookieSession": {
"secret": "<your strong secret>"
},
"admin": {
"username": "IdentityServer4User#domain.com",
"password": "Password"
},
"authorizationServer": {
"tokenValidation": {
"endpoint": "http://localhost:5000/connect/introspect",
"usernameField": "username",
"activeField": "active",
"scope": {
"valid": ["jsreportscope"]
},
"auth": {
"type": "basic",
"basic": {
"clientId": "jsreport",
"clientSecret": "yoursecret"
}
}
}
},
"enabled": true
},
"authorization": {
"enabled": true
},
"sample-template": {
"createSamples": true
}
}
}
But now I can login and access reports from report server if login by only the user IdentityServer4User#domain.com any other users is getting unauthorized error. In the report server console the error is shown like:
error: username "OtherIdentityServer4User#domain.com" returned from authorization server is not a jsreport user. I don not want to add all the identity server users to js report server.

Why I got error: Cannot query field xx on type "Query"?

Although I copied and pasted the graphQL query from the GraphiQL tool after I tested it at GraphiQL successfully , the query returned with an error when I tried it in Apollo client within a reactJS app:
[GraphQL error]: Message: Cannot query field "allStudents" on type "Query"., Location: [object Object], Path: undefined
Here is my implementation:
const link = createHttpLink({
uri: 'http://localhost:8000/graphql',
fetchOptions: { method: "POST" }
});
const client = new ApolloClient({
link: link
});
const GET_STUDENTS = gql`
query getStudents($schoolID: Int!){
allStudents(schoolId: $schoolID){
pickUpLat
pickUpLng
}
}
`;
client
.query({
query: GET_STUDENTS,
variables: { schoolID: 1 }
})
.then(result => console.log(result));
What could be wrong? here is the correct response that I expected:
{
"data": {
"allStudents": [
{
"pickUpLat": 31.9752942479727,
"pickUpLng": 35.8438429235775
},
{
"pickUpLat": 31.9754545979993,
"pickUpLng": 35.8437478537235
}
]
}
}
EDIT
I get expected results using GraphiQL:
EDIT2
I tried to compare the payload between my request and GraphiQL request:
My request's payload: ( it has __typename which I don't know why )
{"operationName":"getStudents","variables":{"schoolID":1},"query":"query getStudents($schoolID: Int) {\n allStudents(schoolId: $schoolID) {\n pickUpLat\n pickUpLng\n __typename\n }\n}\n"}
GraphiQL request's payload:
{"query":"query getStudents($schoolID: Int!){\n allStudents(schoolId: $schoolID){\n pickUpLat\n pickUpLng\n }\n}","variables":{"schoolID":1},"operationName":"getStudents"}
So, they are almost identical, Any idea?
The fault with my query was that I didn't download the new schema.
You can download the schema by using: apollo schema:download --endpoint=http://localhost:8080/graphql schema.json
replace http://localhost:8080/graphql with your server endpoint
You can see more at https://www.apollographql.com/docs/ios/downloading-schema/
In my case, I had defined a query which didn't require any parameters and it would return an array of objects:
myBasicQuery: [BasicAnswer]
type BasicAnswer {
name String
phone String
}
I was getting the error: Cannot query field \"BasicAnswer\" on type \"BasicAnswer\" when I declared it like this:
query myBasicQuery {
BasicAnswer {
name
phone
}
}
Leaving only the fields of BasicAnswer fixed the issue:
query myBasicQuery {
name
phone
}
For anyone else who might be searching for this problem, make sure you're importing ApolloClient from apollo-client package and not other packages.
For anyone that follows apollo-client has now been sunset, in favour of #apollo/client
Here is how you should be constructing a query
Updated #graphql-codegen/cli package to latest version(2.6.2) and it's working fine.
For anybody who use hasura also.
Problem was
query: query_root
# query: Query # wrong value before upgrade
mutation: mutation_root
subscription: subscription_root
}```
Take a look at your entity, it may be missing the #Field() annotation.
Example:
#PrimaryGeneratedColumn()
id: string;//Will not be mapped by GraphQL and you will get OP's error
#Column()
#Field()
name: string;//Will be mapped by GraphQL and you will not get OP's error
This also happens, if you have fragmented your graphqls files and you forgot to define it in codegen.ts.
(java-project)/src/main/resources:
schema.graphqls
search.graphqls
(angular-project)/codegen.ts
const codegen: CodegenConfig = {
overwrite: true,
// add wildcards here, to read all files:
schema: "../projectname/src/main/resources/graphql/*.graphqls",
documents: './src/app/core/graphql/*.ts',
generates: {
....
}
}
If you see this issue in the GraphiQL interface, you may need to merely refresh the page, which downloads the new schema and the error goes away.

How can we set context variables for IBM Watson from backend

I want to pass some values to frontend in form of context variables in IBM Watson through my Node app. How can I achieve it?
I tried to add the value I want to add to current context variable object and sent that back. Still no help. Is there any way I can do it?
Edit:
Right now, I am adding the required value as a new key-value pair to the context object from Node app as follows.
...
let user_name = "MJ"
context.user_name = user_name
response.send({
output: output,
context: JSON.stringfy(context)
})
...
And in Watson Console, in one of the dialogue nodes I have used like,
Hey $user_name, How are you?
But the output I am getting is,
Hey , How are you?
I can see user_name value in the context object, but I can't use it in the way I mentioned above. Is there any other way to do so?
Any help is appreciated. Thanks in advance!
I was having the same problem. My solution was changing the code when you call the IBM server and request .json:
...
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
context: {username : variable},
...
The username I set in Watson Assistant as well as a context, the variable I used a function to get the name though Query (Because in my application, I am calling the chatbot though an IFrame.), but you can use any variable set on javascript.
You can add any value to the Context object, which can be accessed in your Node.JS app and if you send that value to the front-end, then it should be accessible in the UI as well.
Below I've mentioned a sample welcome response from Conversation service. You can access the Context object from the response of Conversation service and add a new key-value pair to that object. In the response, you'll see that I'm accessing a context variable username that has the value MJ, which has been added dynamically to the context.
`
{
"intents": [],
"entities": [],
"input": {
"text": ""
},
"output": {
"text": ["Hello MJ! How can I help you today?"],
"nodes_visited": ["Conversation Start"],
"log_messages": []
},
"context": {
"username": "MJ",
"conversation_id": "5835fa3b-6a1c-4ec5-92f9-22844684670e",
"system": {
"dialog_stack": [{
"dialog_node": "Conversation Start"
}],
"dialog_turn_counter": 1,
"dialog_request_counter": 1,
"_node_output_map": {
"Conversation Start": [0]
}
}
}
`
Now to update the context, fetch the response and add a new key-value pair
`
var convResponse = <responseObj from Conversation call>;
var context = convResponse.context;
//add new value to context
context["new_key"] = "new value";
`
Now the next call that you make to Conversation, use this updated context instead of the context you received from the previous call. You can send back the response from Conversation to the front-end as well which can then be shown to the user.
var payload = {
assistantId: assistantId,
sessionId: req.body.session_id,
context: {
skills: {
"main skill": {
user_defined: {
username: 'John Doe'
}
}
}
},
input: {
message_type: 'text',
text: "blah",
},
};
works for me. Seen here: https://medium.com/#pranavbhatia_26901/watson-assistant-v2-context-sharing-3ca18626ed0d

Resources