W
Wasp3mo ago
hadanator

Extra fields in sign up

I'm trying to add fullname as a data property when a user signs up. I have the following code:
const emailDataSchema = z.object({
email: z.string(),
fullname: z.string(),
})

export const getEmailUserFields = defineUserSignupFields({
email: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
username: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
isAdmin: data => {
const emailData = emailDataSchema.parse(data)
return adminEmails.includes(emailData.email)
},
fullname: data => {
const emailData = emailDataSchema.parse(data)
return emailData.fullname
},
})
const emailDataSchema = z.object({
email: z.string(),
fullname: z.string(),
})

export const getEmailUserFields = defineUserSignupFields({
email: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
username: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
isAdmin: data => {
const emailData = emailDataSchema.parse(data)
return adminEmails.includes(emailData.email)
},
fullname: data => {
const emailData = emailDataSchema.parse(data)
return emailData.fullname
},
})
const signupSchema = z
.object({
fullname: z.string().min(1, 'Name is required'),
email: z
.string()
.min(1, 'Email is required')
.email('Please enter a valid email'),
password: z
.string()
.min(1, 'Password is required')
.min(8, 'Password must be at least 8 characters'),
confirmPassword: z.string().min(1, 'Please confirm your password'),
})
.refine(data => data.password === data.confirmPassword, {
message: 'Passwords do not match',
path: ['confirmPassword'],
})

export function Signup() {
const [showLinkSentView, setShowLinkSentView] = useState<boolean>(false)
const [signupError, setSignupError] = useState<Error | null>(null)
const {
formData,
errors,
isSubmitting,
showPassword,
changeShowPassword,
handleInputChange,
handleSubmit,
} = useFormHandler(signupSchema, async data => {
setSignupError(null)
try {
await signup({ email: data.email, password: data.password })
setShowLinkSentView(true)
} catch (error: unknown) {
setSignupError(error as Error)
}
})
const signupSchema = z
.object({
fullname: z.string().min(1, 'Name is required'),
email: z
.string()
.min(1, 'Email is required')
.email('Please enter a valid email'),
password: z
.string()
.min(1, 'Password is required')
.min(8, 'Password must be at least 8 characters'),
confirmPassword: z.string().min(1, 'Please confirm your password'),
})
.refine(data => data.password === data.confirmPassword, {
message: 'Passwords do not match',
path: ['confirmPassword'],
})

export function Signup() {
const [showLinkSentView, setShowLinkSentView] = useState<boolean>(false)
const [signupError, setSignupError] = useState<Error | null>(null)
const {
formData,
errors,
isSubmitting,
showPassword,
changeShowPassword,
handleInputChange,
handleSubmit,
} = useFormHandler(signupSchema, async data => {
setSignupError(null)
try {
await signup({ email: data.email, password: data.password })
setShowLinkSentView(true)
} catch (error: unknown) {
setSignupError(error as Error)
}
})
in .wasp/out/sdk/wasp/dist/auth/email/actions/signup.d.ts I would expect the fullname property to be present as a required parameter.
20 Replies
kapa.ai
kapa.ai3mo ago
Hi @hadanator. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To add extra fields like fullname to the signup process in Wasp, you need to: 1. Define the extra field on your User entity in your main.wasp file. 2. Configure the backend to handle the extra field using userSignupFields. 3. Update the signup form UI to collect the extra field from the user. From your code, you are correctly defining fullname in your userSignupFields using defineUserSignupFields. This is the right approach for the backend part. However, for the field to be available and required in the generated types (like in .wasp/out/sdk/wasp/dist/auth/email/actions/signup.d.ts), Wasp relies on the fields you define in your userSignupFields and the fields present in your User entity. Important points: - The extra field (fullname) must exist on your User entity in main.wasp. - The userSignupFields object should be imported and referenced in your main.wasp under the correct auth method. - The signup form (UI) must send the fullname field to the backend. If you are using a custom form, ensure you include fullname in the data passed to the signup action. Example: main.wasp
entity User {=psl
id Int @id @default(autoincrement())
email String @unique
fullname String
psl=}

app myApp {
// ...
auth: {
userEntity: User,
methods: {
email: {
userSignupFields: import { userSignupFields } from "@src/auth/signup.js",
},
},
onAuthFailedRedirectTo: "/login"
}
}
entity User {=psl
id Int @id @default(autoincrement())
email String @unique
fullname String
psl=}

app myApp {
// ...
auth: {
userEntity: User,
methods: {
email: {
userSignupFields: import { userSignupFields } from "@src/auth/signup.js",
},
},
onAuthFailedRedirectTo: "/login"
}
}
src/auth/signup.js
import { defineUserSignupFields } from 'wasp/server/auth'
import * as z from 'zod'

const emailDataSchema = z.object({
email: z.string(),
fullname: z.string(),
})
export const userSignupFields = defineUserSignupFields({
email: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
fullname: data => {
const emailData = emailDataSchema.parse(data)
return emailData.fullname
},
})
import { defineUserSignupFields } from 'wasp/server/auth'
import * as z from 'zod'

const emailDataSchema = z.object({
email: z.string(),
fullname: z.string(),
})
export const userSignupFields = defineUserSignupFields({
email: data => {
const emailData = emailDataSchema.parse(data)
return emailData.email
},
fullname: data => {
const emailData = emailDataSchema.parse(data)
return emailData.fullname
},
})
Custom Signup Form When calling signup, make sure to include fullname:
await signup({ email: data.email, password: data.password, fullname: data.fullname })
await signup({ email: data.email, password: data.password, fullname: data.fullname })
Why isn't fullname showing up as required in the generated types? Wasp generates types based on the fields it knows about from your userSignupFields and your User entity. If you have followed the above steps and fullname is still not present as a required parameter, it could be due to: - The User entity in main.wasp does not have a fullname field. - The userSignupFields is not correctly referenced in main.wasp. - You are using a custom signup form but not passing fullname to the signup action. If all of the above are correct and the type is still not generated as expected, it may be a limitation or a bug in the current Wasp codegen. The knowledge sources do not provide details about customizing the generated TypeScript types for the signup action beyond the above steps, so if the type is not generated as expected, you may need to open an issue with the Wasp team or check for updates on this feature [Signup Fields Customization]. Summary:
- Make sure fullname is on your User entity and in userSignupFields. - Pass fullname to the signup action in your form. - If the generated types still don't include fullname, this may be a current limitation not covered in the docs. Let me know if you need more help with a specific step! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @hadanator, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
hadanator
hadanatorOP3mo ago
@kapa.ai I'm using the opensaas template, and I've also converted over to the ts version of main.wasp. Either way, I don't have a definition for User other than in the schema.prisma file. Can you link to some docs that show how I need to define the User entity in the main.wasp.ts file?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To define the User entity for authentication in Wasp, you need to declare it in your main.wasp file, not just in schema.prisma. The Wasp docs show that the User entity should be defined directly in main.wasp (or main.wasp.ts for TypeScript), using the entity keyword and Prisma Schema Language (PSL) inside {=psl ... psl=} blocks. Here’s an example from the docs for a minimal User entity:
entity User {=psl
id Int @id @default(autoincrement())
psl=}
entity User {=psl
id Int @id @default(autoincrement())
psl=}
You can add additional fields as needed, such as fullname:
entity User {=psl
id Int @id @default(autoincrement())
fullname String
psl=}
entity User {=psl
id Int @id @default(autoincrement())
fullname String
psl=}
This definition should be placed in your main.wasp (or main.wasp.ts) file. Wasp uses this to generate the correct Prisma schema and connect your business logic to authentication. You should not rely solely on the schema.prisma file for entity definitions in Wasp—main.wasp is the source of truth for your app’s entities [Entities Explained]. For more details and examples, see: - Auth Entities: Entities Explained - Username & Password Auth: Add the User Entity If you’re using TypeScript, the syntax remains the same in main.wasp.ts—the entity block is still written in PSL inside {=psl ... psl=}. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @hadanator, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
hadanator
hadanatorOP3mo ago
@kapa.ai It would appear this information is out of date, and after v0.14, defining the User in the main.wasp file is no longer necessary. https://wasp.sh/docs/migration-guides/migrate-from-0-13-to-0-14#migrate-to-the-new-schemaprisma-file
Migration from 0.13.X to 0.14.X | Wasp
This guide only covers the migration from 0.13.X to 0.14.X. If you are migrating from 0.11.X or earlier, please read the migration guide from 0.11.X to 0.12.X first.
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Thank you for pointing this out. Based on the knowledge sources provided, there is no information about changes in Wasp v0.14 or later regarding moving the User entity definition exclusively to schema.prisma and removing it from main.wasp. All the available documentation and examples reference defining the User entity in the main.wasp file using the {=psl ... psl=} block [Entities Explained; Add the User Entity]. The knowledge sources do not contain information about the migration to defining entities only in schema.prisma or about changes introduced in v0.14. If you are following documentation from https://wasp.sh/docs/migration-guides/migrate-from-0-13-to-0-14, please note that this is not included in the sources I have access to, so I cannot confirm or provide guidance on that process. If you need information specifically about v0.14 or later, I recommend consulting the official Wasp documentation or migration guides directly, as the knowledge sources here do not cover those updates. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @hadanator, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
hadanator
hadanatorOP3mo ago
Some additional guidance would be helpful. Long story short, the type for the data parameter for the signup action isn't reflecting the additional fullname property I want to pass back. If I don't include it, the signup fails, but the type safety I would expect in my editor doesn't catch it. In fact, if I do add it, compilation fails because fullname doesn't exist in the type.
sachdva
sachdva3mo ago
Very out of date information yeah sometimes bots hallucinate
<SignupForm
appearance={appearance}
additionalFields={[
{
name: 'firstName',
label: `${t('auth.signup.firstName.label', 'First Name')}`,
type: 'input',
validations: {
required: `${t('auth.signup.firstName.required', 'First name is required')}`,
},
},
{
name: 'lastName',
label: `${t('auth.signup.lastName.label', 'Last Name')}`,
type: 'input',
validations: {
required: `${t('auth.signup.lastName.required', 'Last name is required')}`,
},
},
]}
/>
<SignupForm
appearance={appearance}
additionalFields={[
{
name: 'firstName',
label: `${t('auth.signup.firstName.label', 'First Name')}`,
type: 'input',
validations: {
required: `${t('auth.signup.firstName.required', 'First name is required')}`,
},
},
{
name: 'lastName',
label: `${t('auth.signup.lastName.label', 'Last Name')}`,
type: 'input',
validations: {
required: `${t('auth.signup.lastName.required', 'Last name is required')}`,
},
},
]}
/>
Here's an example of more fields in the SignupForm
hadanator
hadanatorOP3mo ago
Yeah I'm not using the SignupForm though. Just the signup action with a custom ui.
sachdva
sachdva3mo ago
oh you're looking at the .wasp folder, hmm I never look inside the build What's the error you get? and it's already in your schema, correct?
hadanator
hadanatorOP3mo ago
Uhh I'd have to go look, basically a network error with something saying that validation failed because fullname is required. And yes it is in my schema
sachdva
sachdva3mo ago
https://wasp.sh/docs/auth/advanced/custom-auth-actions Ah hmm ok maybe someone from wasp can help, I see already a danger icon here!
hadanator
hadanatorOP3mo ago
Yeah I'm not using a custom signup action, just a custom ui and calling the builtin action. Trying to do this: https://wasp.sh/docs/auth/overview#1-defining-extra-fields
Overview | Wasp
Auth is an essential piece of any serious application. That's why Wasp provides authentication and authorization support out of the box.
hadanator
hadanatorOP3mo ago
Although this line from the docs isn't quite clear:
Keep in mind, that these field names need to exist on the userEntity you defined in your main.wasp file e.g. address needs to be a field on the User entity you defined in the schema.prisma file.
Is it in the main.wasp or in the schema.primsa or both? My new property is definitely on my schema though.
Carlos
Carlos3mo ago
Hey @hadanator! I'm part of the Wasp team. Is the only problem that the types are not showing up? That's a known issue and the fix is merged, will be released with the next version: https://github.com/wasp-lang/wasp/pull/2641
hadanator
hadanatorOP3mo ago
Oh yeah that's exactly my problem. Ship it! haha
hadanator
hadanatorOP3mo ago
How often are y'all doing releases?
Carlos
Carlos3mo ago
Currently the process is quite manual (esp. testing) so we don't have a set cadence for it. We'll probably do a release in the next couple weeks. Good news is we're actually right now working on the release process so in the future we can be much faster/automatic in deploying fixes.
hadanator
hadanatorOP3mo ago
Gotcha. Is the workaround for this currently just removing those extra fields from the signup process? If I make the signup request without the extra fields the request fails, but if I add it to the request then compilation fails.
Carlos
Carlos3mo ago
Yep, sadly
hadanator
hadanatorOP3mo ago
Sounds good, looking forward to the next release then. Thanks!

Did you find this page helpful?