add register route

This commit is contained in:
sianida26 2024-02-28 21:21:55 +07:00
parent 2d25e0d9dd
commit cfefeb625e
8 changed files with 69 additions and 16 deletions

View File

@ -1,4 +1,4 @@
import BaseError from "@/core/error/BaseError"; import applicationJsonOnly from "@/core/utils/applicationJsonOnly";
import handleCatchApi from "@/core/utils/handleCatchApi"; import handleCatchApi from "@/core/utils/handleCatchApi";
import AuthError from "@/modules/auth/error/AuthError"; import AuthError from "@/modules/auth/error/AuthError";
import signInSchema from "@/modules/auth/formSchemas/signInSchema"; import signInSchema from "@/modules/auth/formSchemas/signInSchema";
@ -9,13 +9,7 @@ export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
try { try {
if (request.headers.get("Content-Type") !== "application/json") applicationJsonOnly(request.headers)
throw new BaseError({
errorCode: "UNSUPPORTED_CONTENT_TYPE",
message:
"This content type is not supported. Please use application/json instead",
statusCode: 400
});
const data = signInSchema.safeParse(await request.json()); const data = signInSchema.safeParse(await request.json());
if (!data.success){ if (!data.success){

View File

@ -0,0 +1,38 @@
import BaseError from "@/core/error/BaseError";
import applicationJsonOnly from "@/core/utils/applicationJsonOnly";
import handleCatchApi from "@/core/utils/handleCatchApi";
import { createUserSchema } from "@/modules/auth/formSchemas/CreateUserFormSchema";
import createUser from "@/modules/auth/services/createUser";
import mapObjectToFirstValue from "@/utils/mapObjectToFirstValue";
import { NextRequest, NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
try {
applicationJsonOnly(request.headers);
const data = createUserSchema.safeParse(await request.json());
if (!data.success) {
throw new BaseError({
errorCode: "INVALID_FORM_DATA",
message: "",
formErrors: mapObjectToFirstValue(
data.error.flatten().fieldErrors
),
statusCode: 422,
});
}
const result = await createUser({
email: data.data.email,
name: data.data.name,
password: data.data.password,
passwordConfirmation: data.data.passwordConfirmation ?? "",
});
return NextResponse.json(result);
} catch (e) {
return handleCatchApi(e);
}
}

View File

@ -1,21 +1,24 @@
import logger from "../logger/Logger"; import logger from "../logger/Logger";
export const BaseErrorCodes = ["UNKNOWN_ERROR", "UNSUPPORTED_CONTENT_TYPE"] as const; export const BaseErrorCodes = ["UNKNOWN_ERROR", "UNSUPPORTED_CONTENT_TYPE", "INVALID_FORM_DATA"] as const;
interface ErrorOptions { interface ErrorOptions {
message?: string; message?: string;
errorCode: (typeof BaseErrorCodes)[number] | (string & {}); errorCode: (typeof BaseErrorCodes)[number] | (string & {});
statusCode?: number statusCode?: number,
formErrors?: Record<string, string>
} }
class BaseError extends Error { class BaseError extends Error {
public readonly errorCode: (typeof BaseErrorCodes)[number] | (string & {}); public readonly errorCode: (typeof BaseErrorCodes)[number] | (string & {});
public readonly statusCode: number; public readonly statusCode: number;
public readonly formErrors?: ErrorOptions['formErrors'];
constructor(options: ErrorOptions) { constructor(options: ErrorOptions) {
super(options.message ?? "Undetermined Error"); super(options.message ?? "Undetermined Error");
this.errorCode = options.errorCode ?? "UNKNOWN_ERROR"; this.errorCode = options.errorCode ?? "UNKNOWN_ERROR";
this.statusCode = options.statusCode ?? 500; this.statusCode = options.statusCode ?? 500;
this.formErrors = options.formErrors;
Object.setPrototypeOf(this, new.target.prototype); Object.setPrototypeOf(this, new.target.prototype);

View File

@ -11,7 +11,7 @@ interface ErrorOptions {
class ClientError extends Error { class ClientError extends Error {
public readonly errorCode: ErrorOptions['errorCode']; public readonly errorCode: ErrorOptions['errorCode'];
public readonly statusCode: ErrorOptions['statusCode']; public readonly statusCode: ErrorOptions['statusCode'];
public readonly formErrors?: ErrorOptions['formErrors'] public readonly formErrors?: ErrorOptions['formErrors'];
constructor(options: ErrorOptions) { constructor(options: ErrorOptions) {
super(options.message ?? "Undetermined Error"); super(options.message ?? "Undetermined Error");

View File

@ -0,0 +1,11 @@
import BaseError from "../error/BaseError";
export default function applicationJsonOnly(headers: Headers) {
if (headers.get("Content-Type") !== "application/json")
throw new BaseError({
errorCode: "UNSUPPORTED_CONTENT_TYPE",
message:
"This content type is not supported. Please use application/json instead",
statusCode: 400,
});
}

View File

@ -6,6 +6,7 @@ export default function handleCatchApi(e: unknown): NextResponse {
return NextResponse.json({ return NextResponse.json({
code: e.errorCode, code: e.errorCode,
message: e.message, message: e.message,
formErrors: e.formErrors
}, {status: e.statusCode}); }, {status: e.statusCode});
} }
if (e instanceof Error) { if (e instanceof Error) {

View File

@ -6,8 +6,8 @@ import {z} from "zod"
export interface CreateUserSchema { export interface CreateUserSchema {
name: string; name: string;
email: string; email: string;
plainPassword: string; password: string;
plainPasswordConfirmation: string; passwordConfirmation: string;
} }
export const createUserSchema = z export const createUserSchema = z

View File

@ -1,4 +1,3 @@
import DashboardError from "@/modules/dashboard/errors/DashboardError";
import { import {
CreateUserSchema, CreateUserSchema,
createUserSchema, createUserSchema,
@ -8,7 +7,7 @@ import db from "@/core/db";
import AuthError from "../error/AuthError"; import AuthError from "../error/AuthError";
import hashPassword from "../utils/hashPassword"; import hashPassword from "../utils/hashPassword";
import { createJwtToken } from "../utils/createJwtToken"; import { createJwtToken } from "../utils/createJwtToken";
import { cookies } from "next/headers"; import BaseError from "@/core/error/BaseError";
/** /**
* Creates a new user in the database after validating the input data. * Creates a new user in the database after validating the input data.
@ -25,11 +24,12 @@ export default async function createUser(userData: CreateUserSchema) {
//Validate form input //Validate form input
if (!validatedFields.success) { if (!validatedFields.success) {
throw new DashboardError({ throw new BaseError({
errorCode: "INVALID_FORM_DATA", errorCode: "INVALID_FORM_DATA",
formErrors: mapObjectToFirstValue( formErrors: mapObjectToFirstValue(
validatedFields.error.flatten().fieldErrors validatedFields.error.flatten().fieldErrors
), ),
statusCode: 422,
}); });
} }
@ -42,6 +42,7 @@ export default async function createUser(userData: CreateUserSchema) {
throw new AuthError({ throw new AuthError({
errorCode: "USER_ALREADY_EXISTS", errorCode: "USER_ALREADY_EXISTS",
message: "This email already exists", message: "This email already exists",
statusCode: 422,
}); });
} }
@ -59,5 +60,10 @@ export default async function createUser(userData: CreateUserSchema) {
return { return {
token, token,
user: {
name: user.name,
email: user.email,
profilePhotoUrl: user.photoProfile,
},
}; };
} }