Making SvelteKit forms a pleasure to use with comprehensive validation, type safety, and progressive enhancement.
—
Server-side form processing with validation, error handling, data coercion, and integration with SvelteKit's action system. Handles form submissions, file uploads, and provides comprehensive validation results.
The core server-side validation function that processes form data, validates against schemas, and returns structured results for client consumption.
/**
* Validates form data against a schema and returns a structured result
* @param adapter - Validation adapter for the schema
* @param options - Optional configuration for validation
* @returns Promise resolving to SuperValidated result
*/
function superValidate<Out, Message, In>(
adapter: ValidationAdapter<Out, In>,
options?: SuperValidateOptions<Out>
): Promise<SuperValidated<Out, Message, In>>;
/**
* Validates request data against a schema and returns a structured result
* @param data - Request data from various sources (RequestEvent, FormData, etc.)
* @param adapter - Validation adapter for the schema
* @param options - Optional configuration for validation
* @returns Promise resolving to SuperValidated result
*/
function superValidate<Out, Message, In>(
data: RequestEvent | Request | FormData | URLSearchParams | URL | Partial<In> | null | undefined,
adapter: ValidationAdapter<Out, In>,
options?: SuperValidateOptions<Out>
): Promise<SuperValidated<Out, Message, In>>;
interface SuperValidateOptions<Out> {
/** Whether to include validation errors in the result */
errors?: boolean;
/** Unique identifier for the form */
id?: string;
/** Array of field names that have been preprocessed */
preprocessed?: (keyof Out)[];
/** Default values to use when no data is provided */
defaults?: Out;
/** JSON Schema for additional validation */
jsonSchema?: JSONSchema;
/** Whether to use strict validation mode */
strict?: boolean;
/** Whether to allow file uploads */
allowFiles?: boolean;
/** Transport configuration for data handling */
transport?: Transport;
}Usage Examples:
import { superValidate } from "sveltekit-superforms/server";
import { zod } from "sveltekit-superforms/adapters";
import { z } from "zod";
const schema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().min(18)
});
// Load action - create empty form
export const load = async () => {
const form = await superValidate(zod(schema));
return { form };
};
// Form action - validate submitted data
export const actions = {
default: async ({ request }) => {
const form = await superValidate(request, zod(schema));
if (!form.valid) {
return fail(400, { form });
}
// Process valid data
await saveUser(form.data);
return { form };
}
};
// With custom defaults
const form = await superValidate(zod(schema), {
defaults: { name: "John", email: "", age: 25 }
});
// Validate specific data
const form = await superValidate(
{ name: "Alice", email: "alice@example.com", age: 30 },
zod(schema)
);Functions for adding messages and status information to forms, useful for providing feedback to users after form submission.
/**
* Adds a message to a SuperValidated form result
* @param form - The form result to add the message to
* @param message - The message to add
* @param options - Optional status and type configuration
* @returns Updated form with message
*/
function message<T, M>(
form: SuperValidated<T, M>,
message: M,
options?: {
status?: number;
type?: 'error' | 'success' | 'warning' | 'info';
}
): SuperValidated<T, M>;
/**
* Alias for message function
*/
function setMessage<T, M>(
form: SuperValidated<T, M>,
message: M,
options?: {
status?: number;
type?: 'error' | 'success' | 'warning' | 'info';
}
): SuperValidated<T, M>;Usage Examples:
import { message, superValidate } from "sveltekit-superforms/server";
export const actions = {
default: async ({ request }) => {
const form = await superValidate(request, zod(schema));
if (!form.valid) {
return fail(400, { form });
}
try {
await saveUser(form.data);
return message(form, "User created successfully!", {
type: 'success'
});
} catch (error) {
return message(form, "Failed to create user", {
type: 'error',
status: 500
});
}
}
};Functions for setting specific validation errors on form fields, useful for custom validation logic and server-side error handling.
/**
* Sets validation errors on specific form fields
* @param form - The form result to add errors to
* @param path - Field path where the error should be set
* @param error - Error message or array of error messages
* @returns Updated form with errors
*/
function setError<T, M>(
form: SuperValidated<T, M>,
path: FormPath<T> | '',
error: string | string[]
): SuperValidated<T, M>;Usage Examples:
import { setError, superValidate } from "sveltekit-superforms/server";
export const actions = {
default: async ({ request }) => {
const form = await superValidate(request, zod(schema));
if (!form.valid) {
return fail(400, { form });
}
// Custom validation
const emailExists = await checkEmailExists(form.data.email);
if (emailExists) {
return fail(400, {
form: setError(form, 'email', 'Email already exists')
});
}
// Multiple errors
if (form.data.name.includes('admin')) {
return fail(400, {
form: setError(form, 'name', [
'Name cannot contain "admin"',
'Please choose a different name'
])
});
}
// Form-level error
if (someGlobalCondition) {
return fail(400, {
form: setError(form, '', 'Form submission failed')
});
}
return { form };
}
};Functions for managing file uploads and file-related form data processing.
/**
* Processes form data with file handling capabilities
* @param form - The form result to process
* @param callback - Function to handle file processing
* @returns Updated form with file processing results
*/
function withFiles<T, M>(
form: SuperValidated<T, M>,
callback: (files: FormData) => Promise<void> | void
): Promise<SuperValidated<T, M>>;
/**
* Removes files from form data
* @param form - The form result to remove files from
* @param paths - Paths to file fields to remove
* @returns Updated form without specified files
*/
function removeFiles<T, M>(
form: SuperValidated<T, M>,
paths?: FormPath<T>[]
): SuperValidated<T, M>;Usage Examples:
import { withFiles, superValidate } from "sveltekit-superforms/server";
import { writeFile } from 'fs/promises';
const schema = z.object({
name: z.string(),
avatar: z.any() // File field
});
export const actions = {
upload: async ({ request }) => {
const form = await superValidate(request, zod(schema));
if (!form.valid) {
return fail(400, { form });
}
return await withFiles(form, async (files) => {
const avatar = files.get('avatar') as File;
if (avatar && avatar.size > 0) {
const buffer = await avatar.arrayBuffer();
await writeFile(`uploads/${avatar.name}`, Buffer.from(buffer));
}
});
}
};Utility functions for working with validation schemas and extracting metadata.
/**
* Creates default values from a validation adapter
* @param adapter - Validation adapter to extract defaults from
* @param options - Optional configuration
* @returns SuperValidated result with defaults
*/
function defaults<Out, Message, In>(
adapter: ValidationAdapter<Out, In>,
options?: { id?: string; defaults?: Out }
): SuperValidated<Out, Message, In>;
/**
* Extracts default values from a validation adapter
* @param adapter - Validation adapter to extract defaults from
* @returns Default values object
*/
function defaultValues<T>(adapter: ValidationAdapter<T>): T;
/**
* Gets structural shape information from a validation adapter
* @param adapter - Validation adapter to analyze
* @returns Schema shape metadata
*/
function schemaShape<T>(adapter: ValidationAdapter<T>): SchemaShape;
/**
* Splits an object path string into an array of path segments
* @param path - Dot-separated path string (e.g., "user.profile.name")
* @returns Array of path segments (e.g., ["user", "profile", "name"])
*/
function splitPath(path: string): (string | number)[];Functions for creating typed action results that integrate with SvelteKit's form handling system.
/**
* Creates an action result with proper typing
* @param status - HTTP status code
* @param data - Data to include in the result
* @returns Typed ActionResult
*/
function actionResult<T>(
status: number,
data: T
): ActionResult<T>;
/**
* Creates a failure action result with automatic form processing
* Automatically sets valid: false on SuperValidated forms and removes files
* @param status - HTTP status code (typically 400)
* @param data - Data to include in the failure result (usually contains form)
* @returns Failure ActionResult with processed form data
*/
function fail<T>(
status: number,
data: T
): ActionFailure<T>;interface SuperValidated<Out, Message = any, In = Out> {
/** Unique identifier for the form instance */
id: string;
/** Whether the form data passed validation */
valid: boolean;
/** Deprecated: Whether the form was posted (inconsistent behavior) */
posted: boolean;
/** Validation errors structured by field path */
errors: ValidationErrors<Out>;
/** The validated and coerced form data */
data: Out;
/** HTML input constraints derived from schema */
constraints?: InputConstraints<Out>;
/** Optional message for user feedback */
message?: Message;
/** Schema structure metadata */
shape?: SchemaShape;
}
interface ValidationErrors<T> {
/** Form-level errors */
_errors?: string[];
/** Field-level errors following object structure */
[K in keyof T]?: T[K] extends Record<string, unknown>
? ValidationErrors<T[K]>
: T[K] extends Array<infer U>
? U extends Record<string, unknown>
? Array<ValidationErrors<U> | undefined>
: string[]
: string[];
}
interface InputConstraints<T> {
[K in keyof T]?: T[K] extends Record<string, unknown>
? InputConstraints<T[K]>
: T[K] extends Array<infer U>
? U extends Record<string, unknown>
? Array<InputConstraints<U> | undefined>
: InputConstraint
: InputConstraint;
}
interface InputConstraint {
/** Minimum value/length */
min?: number;
/** Maximum value/length */
max?: number;
/** Step value for numbers */
step?: number;
/** Minimum length for strings */
minlength?: number;
/** Maximum length for strings */
maxlength?: number;
/** Regular expression pattern */
pattern?: string;
/** Whether field is required */
required?: boolean;
}
type ValidationAdapter<Out, In = Out> = {
/** Identifier for the validation library used */
superFormValidationLibrary: ValidationLibrary;
/** Validation function that processes data */
validate: (data: unknown) => Promise<ValidationResult<Out>>;
/** JSON Schema representation */
jsonSchema: JSONSchema;
/** Default values for the schema */
defaults: Out;
/** HTML input constraints */
constraints: InputConstraints<Out>;
/** Schema structure metadata */
shape: SchemaShape;
/** Unique identifier for caching */
id: string;
};
type ValidationResult<T> = {
/** Whether validation passed */
success: boolean;
/** Validated data (if successful) */
data?: T;
/** Validation error details */
issues?: ValidationIssue[];
};
interface ValidationIssue {
/** Path to the field with the error */
path: (string | number)[];
/** Error message */
message: string;
/** Error code */
code?: string;
}
type FormPath<T, Type = any> = string; // String path to any property in T
type TaintedFields<T> = Record<string, boolean>; // Tracks modified fieldsInstall with Tessl CLI
npx tessl i tessl/npm-sveltekit-superforms