Closed kristianmandrup closed 4 months ago
I found the following in the tests:
t('with form-level errors', async () => {
const schema = z
.object({
name: z.string()
})
.refine((a) => a.name == 'OK', {
message: 'Name is not OK'
});
const form = await superValidate({ name: 'Test' }, zod(schema));
expect(form.errors).toEqual({
_errors: ['Name is not OK']
});
});
Further investigation required
Source and package.json for the example code, in different branches, here's the zod version: https://github.com/ciscoheat/superforms-examples/tree/zod
Thanks a lot for reaching out so quickly.
Seems to be my VS Code that was caching and not restarting the TS server. Now it no longer complains with the following schema:
export const schema = z
.object({
// newPassword: advancedPasswordSchema,
// confirmPassword: advancedPasswordSchema,
newPassword: z.string().min(8, 'Password must be at least 8 characters long'),
confirmPassword: z.string().min(8, 'Password must be at least 8 characters long'),
passwordResetToken: z.string().optional()
})
.refine((data) => data.newPassword === data.confirmPassword, {
message: " Passwords don't match",
path: ['confirmPassword']
});
However when I run my project I get the following, not sure how to debug.
TypeError: Cannot read properties of undefined (reading 'defaults')
at Module.superValidate
I assume it is from await superValidate(zod(schema))
in my load function
import type { Actions, PageServerLoad } from './$types';
import { eq } from 'drizzle-orm';
import { Argon2id } from 'oslo/password';
import { redirect } from 'sveltekit-flash-message/server';
import { message, superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
import { route } from '$lib/ROUTES';
import {
deleteAllUsers,
deleteSessionCookie,
getAllUsers,
isSameAsOldPassword,
passwordResetDashboardPageActionRateLimiter
} from '$lib/database/authUtils.server';
import { database } from '$lib/database/database.server';
import { lucia } from '$lib/database/luciaAuth.server';
import { usersTable } from '$lib/database/schema';
import { LOGIN_ROUTE } from '$lib/utils/navLinks';
import { schema } from '$validations/AuthZodSchemas';
// import { PasswordResetZodSchema } from '$validations/AuthZodSchemas';
export const load = (async (event) => {
const { cookies, locals } = event;
if (!locals.user) {
throw redirect(
route('/auth/login'),
{
type: 'error',
message: 'You must be logged in to view the dashboard.'
},
cookies
);
}
await passwordResetDashboardPageActionRateLimiter.cookieLimiter?.preflight(event);
return {
loggedInUser: locals.user,
allUsers: await getAllUsers(),
passwordResetFormData: await superValidate(zod(schema))
};
}) satisfies PageServerLoad;
Not sure I understand why defaults is undefined:
With the library installed and the adapter imported, all you need to do is wrap the schema with it:
import { superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';
const form = await superValidate(zod(schema));
The libraries in the list that requires defaults don’t have full introspection capabilities (yet), in which case you need to supply the default values for the form data as an option:
import { type } from 'arktype';
// Arktype schema, powerful stuff
const schema = type({
name: 'string',
email: 'email',
tags: '(string>=2)[]>=3',
score: 'integer>=0'
});
const defaults = { name: '', email: '', tags: [], score: 0 };
export const load = async () => {
const form = await superValidate(arktype(schema, { defaults }));
return { form };
};
But zod
shouldn't require defaults?
Zod doesn't require defaults, and works in hundreds of tests, so I'm not sure why that happens for you.
I'm sorry, I think I'm confused about which superValidate
to use. The error references the following:
/**
* Validates a schema for data validation and usage in superForm.
* @param data Data corresponding to a schema, or RequestEvent/FormData/URL. If falsy, the schema's default values will be used.
* @param schema The schema to validate against.
*/
export async function superValidate(data, adapter, options) {
if (data && 'superFormValidationLibrary' in data) {
options = adapter;
adapter = data;
data = undefined;
}
const validator = adapter;
const defaults = options?.defaults ?? validator.defaults;
and here validator
is undefined
.
So it seems there are the following variants?
import { superValidate } from 'sveltekit-superforms';
import { superValidate } from 'sveltekit-superforms/client';
import { superValidate } from 'sveltekit-superforms/server';
But both client and server references the root superValidate
. Now the error seems to stem from calling it with a single argument zod(schema)
which is the data
argument, leaving the adapter
argument empty and hence this part failing:
const defaults = options?.defaults ?? validator.defaults;
Strange.
Which is in line with the example in the docs:
import { error } from '@sveltejs/kit';
export const load = async ({ params }) => {
// Replace with your database
const user = db.users.findUnique({
where: { id: params.id }
});
if (!user) error(404, 'Not found');
const form = await superValidate(user, your_adapter(schema));
// Always return { form } in load functions
return { form };
};
So I guess I could use the following for initial load?
return {
loggedInUser: locals.user,
allUsers: await getAllUsers(),
passwordResetFormData: await superValidate({}, zod(schema))
};
Works now :)
Description
package.json
AuthZodSchemas.ts
+page.server.ts
It complains with the following:
Makes no sense to me. I assumed
refine
was the issue, butrefine
is mentioned explicitly in the docs: https://superforms.rocks/concepts/error-handling#form-level-and-array-errorsThe code was taken from an app where it used to work just fine with a previous version of zod and superforms (before using adapter).
I looked at the following issues:
A the end @ciscoheat states: "Superforms v2 will handle this properly."
If applicable, a MRE Use this template project to create a minimal reproducible example that you can link to here: https://sveltelab.dev/github.com/ciscoheat/superforms-examples/tree/zod (right click to open in a new tab)
I tried to update the template, but was not clear how to save and share it. The following modifications to showcase the issue seems to work just fine however...
In my project when I mirrored this it didn't work, so I wonder what the versions are in that MRE sample repo. Didn't seem to be able to view package.json however