Hey guys, really nice job the one you are doing here. Very excited to be adopting this framework on such an early stage. Hope to contribute on its growth, at least asking some silly questions.
I have been playing around with the new auth API and itās great, good job!
Now Iām trying to create a user object in the db after a signup is verified in Netlify but I get a Prisma error Invalid prisma.user.create()
invocation (complete error below).
Approach:
To set a webbook notification from Netlify to a custom Function that triggers createUser
service with the data of the event.
The question:
Itās possible to import and reuse the service function createUser()
created with scaffold inside another Function (lambda), what is the correct way?
On the docs says:
But you could still use it yourselfāservices are just Javascript functions so you can use them anywhere youād like:
From another service
In a custom lambda function
From a completely separate, custom API
I tried to reuse the API service for the User
object, but I couldnāt. Ended up using the solution in this ticket, re-importing Prisma client.
What I tried so far:
Iāve imported a service inside handleSignup.js
Function, it receives a webhook from Netlify when a user sign ups
// /api/src/functions/handleSignup.js
import { createUser } from 'src/services/users/users'
Then I call it with await with the input data as object:
// /api/src/functions/handleSignup.js
export const handler = async (event, context) => {
const data = JSON.parse(event.body);
const { user } = data;
const newUser = await createUser({
role: 'admin',
email: user.email, // 'leoalbin@gmail.com'
name: user.user_metadata.full_name // 'Leo Test'
} )
...
// some other stuff and response
And I get this error:
PrismaClientValidationError:
00:09:29 api | Invalid `prisma.user.create()` invocation in
00:09:29 api | /Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/api/src/services/users/users.js:14:18
00:09:29 api |
00:09:29 api | {
00:09:29 api | + data: {
00:09:29 api | + id?: String,
00:09:29 api | + role: String,
00:09:29 api | + email: String,
00:09:29 api | + name?: String,
00:09:29 api | + createdAt?: DateTime
00:09:29 api | + }
00:09:29 api | }
00:09:29 api |
00:09:29 api | Argument data is missing.
00:09:29 api |
00:09:29 api | Note: Lines with + are required
00:09:29 api |
00:09:29 api | at Document.validate (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/@prisma/client/src/runtime/query.ts:256:19)
00:09:29 api | at Object.model [as User] (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/@prisma/client/src/runtime/getPrismaClient.ts:394:20)
00:09:29 api | at Object.create (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/@prisma/client/src/runtime/getPrismaClient.ts:519:33)
00:09:29 api | at createUser (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/api/src/services/users/users.js:14:18)
00:09:29 api | at handler (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/api/src/functions/handleSignup.js:24:25)
00:09:29 api | at /Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/@redwoodjs/dev-server/src/main.ts:169:26
00:09:29 api | at Layer.handle [as handle_request] (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/express/lib/router/layer.js:95:5)
00:09:29 api | at next (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/express/lib/router/route.js:137:13)
00:09:29 api | at next (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/express/lib/router/route.js:131:14)
00:09:29 api | at next (/Volumes/Documentos/Produccion/WILDTRACKING/wildtracking/node_modules/express/lib/router/route.js:131:14)
This is my sdl file for Users:
export const schema = gql`
type User {
id: String!
role: String!
email: String!
name: String
createdAt: DateTime!
}
type Query {
users: [User!]!
user(id: String!): User!
}
input CreateUserInput {
role: String!
email: String!
name: String
}
input UpdateUserInput {
role: String
email: String
name: String
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: String!, input: UpdateUserInput!): User!
deleteUser(id: String!): User!
}
`
And the service file:
// api/src/services/users/users.js
import { db } from 'src/lib/db'
export const users = () => {
return db.user.findMany()
}
export const user = ({ id }) => {
return db.user.findOne({
where: { id },
})
}
export const createUser = ({ input }) => {
return db.user.create({
data: input,
})
}
export const updateUser = ({ id, input }) => {
return db.user.update({
data: input,
where: { id },
})
}
export const deleteUser = ({ id }) => {
return db.user.delete({
where: { id },
})
}
I did this and finally got it to work:
// /api/src/functions/handleSignup.js
const { PrismaClient } = require('@prisma/client')
const dotenv = require('dotenv')
dotenv.config()
const db = new PrismaClient()
export const handler = async (event, context) => {
const data = JSON.parse(event.body);
const { user } = data;
//this response modify the data in Netlify
const responseBody = {
app_metadata: {
roles: ["admin"],
my_user_info: "this is some user info"
},
user_metadata: {
...user.user_metadata, // append current user metadata
custom_data_from_function: "hurray this is some extra metadata"
}
}
const newUser = await db.user.create(
{ data: {
role: 'admin',
email: user.email,
name: user.user_metadata.full_name
}
} )
db.disconnect()
if(newUser.id) {
const newAccount = await db.account.create(
{ data: {
adminUserId: newUser.id,
}
} )
db.disconnect()
}
return {
statusCode: 200,
body: JSON.stringify(responseBody),
}
}
But I would like to reuse the functions from the services as my database interface. Is that ok or the services were not for that?
What Iām missing here?
Thanks a lot