mirror of
https://github.com/tiennm99/bsk.git
synced 2026-09-03 02:19:34 +00:00
- app/, components/, lib/, i18n/, tests/, proxy renamed via git mv - types carried into JSDoc: @template generics, @typedef aliases, /** @type */ casts where TS had as-casts or non-null assertions - role tuple keeps its const assertion; the db-enum drift guard now checks the tuple values against the generated enum type - use client/use server directives and server-only imports preserved - prettier-formatted; vitest suite unchanged
69 lines
2.5 KiB
JavaScript
69 lines
2.5 KiB
JavaScript
/**
|
|
* BSK sign-in schema and shared state types.
|
|
*
|
|
* No `'use server'` here — this module is framework-agnostic so it can be
|
|
* imported by both client code (RHF resolver) and server code (actions).
|
|
*
|
|
* Zod v4: z.string().email() | z.string().min(8).max(72)
|
|
* 72 = bcrypt's effective byte limit, matching Supabase's default password cap.
|
|
*/
|
|
import { z } from "zod";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Schema
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const SignInSchema = z.object({
|
|
email: z.string().email(),
|
|
password: z.string().min(8).max(72),
|
|
});
|
|
|
|
/** @typedef {import("zod").infer<typeof SignInSchema>} SignInInput */
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Discriminated-union state — returned by signInAction, consumed by useActionState
|
|
//
|
|
// All variants must be JSON-serializable (no Error objects, no Date, no functions)
|
|
// so they can cross the RSC/client boundary without crashing serialization.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @typedef {object} SignInErrorState
|
|
* @property {"error"} status
|
|
* @property {Record<string, string[]>} fieldErrors Per-field validation errors keyed by field name.
|
|
* @property {string | null} formError Non-field error (auth failure, server error). Null when fieldErrors are set.
|
|
*/
|
|
|
|
/** @typedef {{ status: "idle" } | SignInErrorState} SignInState */
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helper
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Parses a raw FormData submission against `SignInSchema`.
|
|
*
|
|
* Returns `{ success: true, data }` on valid input, or
|
|
* `{ success: false, fieldErrors }` on invalid input.
|
|
*
|
|
* Extracts entries via `Object.fromEntries` — safe because FormData entries
|
|
* here are single-value strings (email + password).
|
|
*
|
|
* @param {FormData} formData
|
|
* @returns {{ success: true; data: SignInInput } | { success: false; fieldErrors: Record<string, string[]> }}
|
|
*/
|
|
export function parseSignIn(formData) {
|
|
const result = SignInSchema.safeParse(Object.fromEntries(formData));
|
|
|
|
if (!result.success) {
|
|
// Zod v4: flatten() still produces { fieldErrors, formErrors }
|
|
const flat = result.error.flatten();
|
|
return {
|
|
success: false,
|
|
fieldErrors: /** @type {Record<string, string[]>} */ (flat.fieldErrors),
|
|
};
|
|
}
|
|
|
|
return { success: true, data: result.data };
|
|
}
|