waveform/lib/services/auth.service.ts

134 lines
3.9 KiB
TypeScript

/**
* @file app/lib/services/auth.service.ts
* @description Authentication service providing helper functions for sign-in, and registration.
*/
import { loginSchema, registerSchema } from "@/lib/schemas/auth.schema";
import { signIn } from "next-auth/react";
/**
* Authenticates a user using email and password credentials, performing client-side validation first.
*
* @async
* @param {string} email - The user's email address.
* @param {string} password - The user's account password.
* @returns {Promise<{ success?: boolean; error?: string }>} An object indicating sign-in success or an error message.
*/
export async function loginUser(email: string, password: string) {
const validationResult = loginSchema.safeParse({ email, password });
if (!validationResult.success) {
return { error: validationResult.error.issues[0].message };
}
try {
const res = await signIn("credentials", {
email: validationResult.data.email,
password: validationResult.data.password,
redirect: false,
});
if (res?.error) {
if (res.error === "CredentialsSignin") {
return { error: "Incorrect email address or password." };
}
return { error: "An unexpected error has occurred." };
}
return { success: true };
} catch (err: any) {
if (
err?.message?.includes("fetch") ||
err?.name === "TypeError" ||
err?.message?.includes("network")
) {
return { error: "Server error: API endpoint not available" };
}
return { error: err?.message || "An unexpected error has occurred." };
}
}
/**
* Registers a new user account by validating the form data and submitting it to the backend registration route.
*
* @async
* @param {Record<string, any>} payload - The user registration form payload containing credentials and user details.
* @returns {Promise<{ success?: boolean; error?: string }>} An object indicating successful registration or an error message.
*/
export async function registerUser(payload: Record<string, any>) {
const validationResult = registerSchema.safeParse(payload);
if (!validationResult.success) {
return { error: validationResult.error.issues[0].message };
}
try {
const response = await fetch("/api/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(validationResult.data),
});
const contentType = response.headers.get("content-type");
let data;
if (contentType && contentType.includes("application/json")) {
try {
data = await response.json();
} catch (jsonErr) {
return { error: "Server error: Invalid response format" };
}
} else {
throw new Error("Server error: API endpoint not available");
}
if (!response.ok) {
return { error: data.message || "Something went wrong." };
}
const loginResult = await autoLogin(
validationResult.data.email,
validationResult.data.password,
);
if (!loginResult.success) {
return { error: loginResult.error };
}
return { success: true };
} catch (err: any) {
return { error: err.message || "Something went wrong." };
}
}
/**
* Performs client-side automatic login using user credentials.
*
* @async
* @param {string} email - The user's email address.
* @param {string} password - The user's password.
* @returns {Promise<{ success: boolean; error?: string }>} The result of the sign-in operation.
*/
export async function autoLogin(email: string, password: string) {
try {
const signInResult = await signIn("credentials", {
email,
password,
redirect: false,
});
if (signInResult?.error) {
return {
success: false,
error: "Automatic sign-in failed. Please log in manually.",
};
}
return { success: true };
} catch (err: any) {
return {
success: false,
error: err?.message || "An unexpected error occurred during auto-login.",
};
}
}