Reputation: 55
@Mutation (() => UserResponse)
async register(
@Arg('options', () => UsernamePasswordInput ) options: UsernamePasswordInput,
@Ctx() {em, req}: MyContext
): Promise<UserResponse>{
const errors = validateRegister(options);
const hashedPassword = await argon2.hash(options.password)
let user;
try{
/* cast to this type, em as entity manager */
const result = await (em as EntityManager).createQueryBuilder(User).getKnexQuery().insert({
username: options.username,
password: hashedPassword,
email: options.email,
created_at: new Date(),
updated_at: new Date()
}).returning("*");
/* returns all fields back from the user */
user = result[0];
} catch(err: any ) {
if (err.code === '23505' || err.detail.includes("already exists")){
// duplicate name
/* returning errors object */
return {
errors: [{
field: 'username or email',
message: 'that username or email already exists'
}]
}
}
}
req.session.userId = user.id;
return {user};
}
import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
import { Field, Int, ObjectType } from "type-graphql";
@ObjectType()
@Entity()
export class User {
@Field(() => Int)
@PrimaryKey()
id!: number;
@Field(() => String )
@Property({type: "date", default: "Now()", nullable: true})
createdAt = new Date();
@Field(() => String )
@Property({type: "date",onUpdate: () => new Date()})
updatedAt = new Date();
@Field(() => String)
@Property({type: 'text', unique: true})
username!: string;
@Field(() => String)
@Property({type: "text", unique: true})
email!: string;
/* this password has no graphql endpoint field */
@Property({type: 'text'})
password!: string;
}
const Register: React.FC<registerProps> = ({}) => {
const router = useRouter();
const [, register] = useRegisterMutation();
return (
<Wrapper variant = "small">
<Formik
initialValues = {{email: "", username: "", password: ""}}
onSubmit = {
async (values, {setErrors}) => {
/* this is a promise retruned therefore just return */
/* maps to the graphql mutation specified above */
const response = await register({options: values});
console.log("user: ", response)
/* code gen is detecting the types of this response from graphql */
/* check if the errors object has any errors */
if (response.data?.register.errors){
/* map then into a key:value pair for use in the formik set errors to nicely display the errors */
setErrors(toErrorMap(response.data.register.errors));
} else if(response.data?.register.user){
// worked
/* use next js hook to return to homepage */
router.push('/');
}
}}>
{/*
this is a render prop, we are taking values state and handleChange function from Formik , and passing our logic in
using the handles they gave us.
*/}
{({isSubmitting}) => (
<Form>
<InputField
name = "username"
placeholder = "username"
label = "Username"
/>
<Box mt = {4}>
<InputField
name = "email"
placeholder = "email"
label = "Email"
/>
</Box>
<Box mt = {4}>
<InputField
name = "password"
placeholder = "password"
label = "Password"
type = "password"
/>
</Box>
<Button
_hover = {{
backgroundColor: "purple",
color: "white",
}}
ml = "auto"
mr = "auto"
mt = {4}
display = "block"
type = "submit"
backgroundColor = "black"
/* this loads whenever we are submittting, a cool loading symbol */
isLoading = {isSubmitting}
>
register
</Button>
</Form>
)}
</Formik>
</Wrapper>
)
}
export default withUrqlClient(createUrqlClient, {ssr: true})(Register);
On my page when I pass an email / password / username to register it returns this error from graphql
{
"errors": [
{
"message": "Cannot return null for non-nullable field User.createdAt.",
"locations": [
{
"line": 10,
"column": 7
}
],
"path": [
"register",
"user",
"createdAt"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Cannot return null for non-nullable field User.createdAt.",
" at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:559:13)",
" at resolveField (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:472:19)",
" at executeFields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:292:18)",
" at collectAndExecuteSubfields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:748:10)",
" at completeObjectValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:738:10)",
" at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:590:12)",
" at resolveField (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:472:19)",
" at executeFields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:292:18)",
" at collectAndExecuteSubfields (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:748:10)",
" at completeObjectValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:738:10)",
" at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:590:12)",
" at completeValue (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:556:21)",
" at D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\graphql\\execution\\execute.js:469:16",
" at processTicksAndRejections (node:internal/process/task_queues:96:5)",
" at async execute (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:205:20)",
" at async Object.processGraphQLRequest (D:\\Coding\\WebDevelopment\\Projects\\lireddit\\server\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:139:28)"
]
}
}
}
],
"data": {
"register": {
"errors": null,
"user": null
}
}
}
This happens for no known reason , and I really am not sure what to even say at this point I have been confused on this issue for ages
......................... . .. . . . . . . ...................................................................................................................................................................
Upvotes: 3
Views: 16007
Reputation: 1870
Same tutorial. In src/resolvers/user.ts at the end of the try
clause of the register
mutation replace returning('*')
with
.returning([
'*',
'created_at as createdAt',
'updated_at as updatedAt'
])
That shapes the server response to
result: [
{
id: 00,
username: 'jonh_d',
createdAt: 1985-10-29T03:17:23.000Z,
updatedAt: 1985-10-29T03:17:23.000Z
}
]
Upvotes: 1
Reputation: 1074
This usually always happens when a field, which is set up as non-nullable, is being returned as null from the server.
Please check the object which is returned from the server and verify if all the fields which you marked as per your set up, are being returned with some value.
One way to quickly check is to make all as { nullable: true }
and see if that works, and then you can see which one is the offender.
Upvotes: 1