Notes route

This commit is contained in:
Sanjib Sen 2025-01-16 12:37:06 +06:00
parent 0fe2b335ed
commit 9f706092a7
14 changed files with 546 additions and 141 deletions

View file

@ -3,7 +3,7 @@ import { defineConfig } from "drizzle-kit";
export default defineConfig({ export default defineConfig({
out: "./drizzle", out: "./drizzle",
schema: "./src/db/schema.ts", schema: "./src/db/schema",
dialect: "postgresql", dialect: "postgresql",
dbCredentials: { dbCredentials: {
url: process.env.DATABASE_URL!, url: process.env.DATABASE_URL!,

View file

@ -1,4 +1,6 @@
CREATE TABLE "account" ( CREATE SCHEMA "auth";
--> statement-breakpoint
CREATE TABLE "auth"."account" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL, "account_id" text NOT NULL,
"provider_id" text NOT NULL, "provider_id" text NOT NULL,
@ -14,14 +16,14 @@ CREATE TABLE "account" (
"updated_at" timestamp NOT NULL "updated_at" timestamp NOT NULL
); );
--> statement-breakpoint --> statement-breakpoint
CREATE TABLE "rate_limit" ( CREATE TABLE "auth"."rate_limit" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"key" text, "key" text,
"count" integer, "count" integer,
"last_request" integer "last_request" integer
); );
--> statement-breakpoint --> statement-breakpoint
CREATE TABLE "session" ( CREATE TABLE "auth"."session" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"expires_at" timestamp NOT NULL, "expires_at" timestamp NOT NULL,
"token" text NOT NULL, "token" text NOT NULL,
@ -33,7 +35,7 @@ CREATE TABLE "session" (
CONSTRAINT "session_token_unique" UNIQUE("token") CONSTRAINT "session_token_unique" UNIQUE("token")
); );
--> statement-breakpoint --> statement-breakpoint
CREATE TABLE "user" ( CREATE TABLE "auth"."user" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL, "name" text NOT NULL,
"email" text NOT NULL, "email" text NOT NULL,
@ -44,7 +46,7 @@ CREATE TABLE "user" (
CONSTRAINT "user_email_unique" UNIQUE("email") CONSTRAINT "user_email_unique" UNIQUE("email")
); );
--> statement-breakpoint --> statement-breakpoint
CREATE TABLE "verification" ( CREATE TABLE "auth"."verification" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL, "identifier" text NOT NULL,
"value" text NOT NULL, "value" text NOT NULL,
@ -53,5 +55,15 @@ CREATE TABLE "verification" (
"updated_at" timestamp "updated_at" timestamp
); );
--> statement-breakpoint --> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint CREATE TABLE "note" (
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action; "id" text PRIMARY KEY NOT NULL,
"title" text,
"content" text,
"createdAt" timestamp DEFAULT now(),
"updatedAt" timestamp,
"ownerId" text NOT NULL
);
--> statement-breakpoint
ALTER TABLE "auth"."account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "auth"."session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "note" ADD CONSTRAINT "note_ownerId_user_id_fk" FOREIGN KEY ("ownerId") REFERENCES "auth"."user"("id") ON DELETE no action ON UPDATE no action;

View file

@ -1,12 +1,12 @@
{ {
"id": "e9e52dc2-cfab-453f-8e23-57a32259b8e9", "id": "806f9895-fec6-43da-9c78-46e599e611e8",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
"tables": { "tables": {
"public.account": { "auth.account": {
"name": "account", "name": "account",
"schema": "", "schema": "auth",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -93,6 +93,7 @@
"name": "account_user_id_user_id_fk", "name": "account_user_id_user_id_fk",
"tableFrom": "account", "tableFrom": "account",
"tableTo": "user", "tableTo": "user",
"schemaTo": "auth",
"columnsFrom": [ "columnsFrom": [
"user_id" "user_id"
], ],
@ -109,9 +110,9 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.rate_limit": { "auth.rate_limit": {
"name": "rate_limit", "name": "rate_limit",
"schema": "", "schema": "auth",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -146,9 +147,9 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.session": { "auth.session": {
"name": "session", "name": "session",
"schema": "", "schema": "auth",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -205,6 +206,7 @@
"name": "session_user_id_user_id_fk", "name": "session_user_id_user_id_fk",
"tableFrom": "session", "tableFrom": "session",
"tableTo": "user", "tableTo": "user",
"schemaTo": "auth",
"columnsFrom": [ "columnsFrom": [
"user_id" "user_id"
], ],
@ -229,9 +231,9 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.user": { "auth.user": {
"name": "user", "name": "user",
"schema": "", "schema": "auth",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -292,9 +294,9 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.verification": { "auth.verification": {
"name": "verification", "name": "verification",
"schema": "", "schema": "auth",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -340,10 +342,77 @@
"policies": {}, "policies": {},
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
},
"public.note": {
"name": "note",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"ownerId": {
"name": "ownerId",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"note_ownerId_user_id_fk": {
"name": "note_ownerId_user_id_fk",
"tableFrom": "note",
"tableTo": "user",
"schemaTo": "auth",
"columnsFrom": [
"ownerId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
} }
}, },
"enums": {}, "enums": {},
"schemas": {}, "schemas": {
"auth": "auth"
},
"sequences": {}, "sequences": {},
"roles": {}, "roles": {},
"policies": {}, "policies": {},

View file

@ -5,8 +5,8 @@
{ {
"idx": 0, "idx": 0,
"version": "7", "version": "7",
"when": 1736964339376, "when": 1736970092723,
"tag": "0000_bright_meltdown", "tag": "0000_pretty_banshee",
"breakpoints": true "breakpoints": true
} }
] ]

View file

@ -1,25 +1,141 @@
import { Memo } from "./note.model"; import { and, eq, notExists } from "drizzle-orm";
import { db } from "../../db";
import { note } from "../../db/schema/note";
import { CreateNote } from "./note.model";
export class Note { export class NoteController {
constructor( async createNote(new_note: CreateNote, ownerId: string) {
public data: Memo[] = [ const new_note_data = { ...new_note, ownerId: ownerId };
{ const result = await db
data: "Moonhalo", .insert(note)
}, .values(new_note_data)
] .returning({
) {} id: note.id,
title: note.title,
add(note: Memo) { content: note.content,
this.data.push(note); createdAt: note.createdAt,
updatedAt: note.updatedAt,
return this.data; })
.execute();
return {
success: true,
data: result,
message: "Note created successfully",
error: null,
};
} }
remove(index: number) { async getOwnerNotes(ownerId: string, limit:number=10, offset:number=0) {
return this.data.splice(index, 1); const result = await db
.select({
id: note.id,
title: note.title,
content: note.content,
createdAt: note.createdAt,
updatedAt: note.updatedAt,
})
.from(note)
.where(and(eq(note.ownerId, ownerId), notExists(note.deletedAt)))
.limit(limit).offset(offset)
.execute();
return {
success: true,
data: result,
message: "",
error: null,
};
} }
update(index: number, note: Partial<Memo>) { async getNoteById(noteId: string, ownerId: string) {
return (this.data[index] = { ...this.data[index], ...note }); const result = await db
.select({
id: note.id,
title: note.title,
content: note.content,
createdAt: note.createdAt,
updatedAt: note.updatedAt,
})
.from(note)
.where(
and(
eq(note.id, noteId),
eq(note.ownerId, ownerId),
notExists(note.deletedAt)
)
)
.execute();
return {
success: true,
data: result,
message: "",
error: null,
};
}
async updateNoteById(
noteId: string,
updated_note: CreateNote,
ownerId: string
) {
const new_note_data = { ...updated_note, updatedAt: new Date() };
const result = await db
.update(note)
.set(new_note_data)
.where(
and(
eq(note.id, noteId),
eq(note.ownerId, ownerId),
notExists(note.deletedAt)
)
)
.returning({
id: note.id,
title: note.title,
content: note.content,
createdAt: note.createdAt,
updatedAt: note.updatedAt,
})
.execute();
return {
success: true,
data: result,
message: "Note updated successfully",
error: null,
};
}
async deleteNoteById(noteId: string, ownerId: string) {
await db
.update(note)
.set({ deletedAt: new Date() })
.where(
and(
eq(note.id, noteId),
eq(note.ownerId, ownerId),
notExists(note.deletedAt)
)
)
.execute();
return {
success: true,
data: null,
message: "Note deleted successfully",
error: null,
};
}
async deleteAllNotes(ownerId: string) {
await db
.update(note)
.set({ deletedAt: new Date() })
.where(and(eq(note.ownerId, ownerId), notExists(note.deletedAt)))
.execute();
return {
success: true,
data: null,
message: "Notes deleted successfully",
error: null,
};
} }
} }

View file

@ -1,7 +1,37 @@
import { createSelectSchema } from "drizzle-typebox";
import { t } from "elysia"; import { t } from "elysia";
import { note } from "../../db/schema/note";
import { InferInsertModel, InferSelectModel } from "drizzle-orm";
export const memoSchema = t.Object({
data: t.String(),
});
export type Memo = typeof memoSchema.static; export const SelectNoteSchema = createSelectSchema(note);
export const NoteSchema = t.Omit(SelectNoteSchema, ["deletedAt", "ownerId"]);
export type Note = InferSelectModel<typeof note>;
export type CreateNote = Pick<
InferInsertModel<typeof note>,
"title" | "content"
>;
export const createNoteSchema = t.Pick(NoteSchema, [
"title",
"content",
]);
export const successGetNoteResponse = t.Object({
success:t.Boolean({default:true}),
data: t.Array(NoteSchema),
error: t.Null(),
message: t.String()
}, {
description:"Success"
})
export const successDeleteNoteResponse = t.Object({
success:t.Boolean({default:true}),
data: t.Null(),
error: t.Null(),
message: t.String({default:"Note deletion succesful"})
}, {
description:"Success"
})

View file

@ -1,44 +1,129 @@
import { Elysia, t } from "elysia"; import { Elysia, error, t } from "elysia";
import { Note } from "./note.controller"; import { createNoteSchema, NoteSchema, successDeleteNoteResponse, successGetNoteResponse } from "./note.model";
import { memoSchema } from "./note.model"; import { NoteController } from "./note.controller";
import { userMiddleware } from "../../middlewares/auth-middleware";
import { commonResponses } from "../../lib/utils/common";
export const note = new Elysia({ prefix: "/note" }) export const noteRouter = new Elysia({
.decorate("note", new Note()) prefix: "/note",
name: "CRUD Operations for Notes",
"analytic":true,
tags: ["Note"],
detail: {
description: "Notes CRUD operations",
},
})
.decorate("note", new NoteController())
.model({ .model({
memo: t.Omit(memoSchema, ["author"]), note: NoteSchema,
})
.get("/", ({ note }) => note.data)
.put("/", ({ note, body: { data } }) => note.add({ data }), {
body: "memo",
}) })
.derive(({ request }) => userMiddleware(request))
.get( .get(
"/:index", "",
({ note, params: { index }, error }) => { async ({ note, user, query}) => {
return note.data[index] ?? error(404, "Not Found :("); return await note.getOwnerNotes(user.id, query.limit, query.offset);
}, },
{ {
params: t.Object({ query:t.Object({
index: t.Number(), limit: t.Optional(t.Number()),
offset: t.Optional(t.Number())
}), }),
response:{
200: successGetNoteResponse,
...commonResponses
},
detail:{
"description":"Get all notes of the user",
"summary":"Get all notes"
}
} }
) )
.guard({ .get(
params: t.Object({ ":id",
index: t.Number(), async ({ note, user, params:{id} }) => {
}), return await note.getNoteById(id, user.id);
})
.delete("/:index", ({ note, params: { index }, error }) => {
if (index in note.data) return note.remove(index);
return error(422);
})
.patch(
"/:index",
({ note, params: { index }, body: { data }, error }) => {
if (index in note.data) return note.update(index, { data });
return error(422);
}, },
{ {
body: "memo", params:t.Object({
id: t.String(),
}),
response: {
200: successGetNoteResponse,
...commonResponses
},
detail:{
"description":"Get a note by Id",
"summary":"Get a note"
}
} }
); )
.post(
"",
async ({ body, note, user }) => {
return await note.createNote(body, user.id);
},
{
body: createNoteSchema,
response: {
200: successGetNoteResponse,
...commonResponses
},
detail:{
"description":"Create a new note",
"summary":"Create a note"
}
}
).patch(
":id",
async ({ body, note, user, params:{id} }) => {
return await note.updateNoteById(id, body, user.id);
},
{
body: createNoteSchema,
params:t.Object({
id: t.String(),
}),
response: {
200: successGetNoteResponse,
...commonResponses
},
detail:{
"description":"Update a note by Id",
"summary":"Update a note"
}
}
).delete(
":id",
async ({ note, user, params:{id} }) => {
return await note.deleteNoteById(id, user.id);
},
{
params:t.Object({
id: t.String(),
}),
response: {
200: successDeleteNoteResponse,
...commonResponses
},
detail:{
"description":"Delete a note by Id",
"summary":"Delete a note"
}
}
)
.delete(
"",
async ({ note, user }) => {
return await note.deleteAllNotes(user.id);
},
{
response: {
200: successDeleteNoteResponse,
...commonResponses
},
detail:{
"description":"Delete all notes of an user",
"summary":"Delete all notes"
}
}
)

View file

@ -1,54 +0,0 @@
import { pgTable, text, integer, timestamp, boolean } from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
emailVerified: boolean('email_verified').notNull(),
image: text('image'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});
export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp('expires_at').notNull(),
token: text('token').notNull().unique(),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
ipAddress: text('ip_address'),
userAgent: text('user_agent'),
userId: text('user_id').notNull().references(()=> user.id)
});
export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text('account_id').notNull(),
providerId: text('provider_id').notNull(),
userId: text('user_id').notNull().references(()=> user.id),
accessToken: text('access_token'),
refreshToken: text('refresh_token'),
idToken: text('id_token'),
accessTokenExpiresAt: timestamp('access_token_expires_at'),
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
scope: text('scope'),
password: text('password'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text('identifier').notNull(),
value: text('value').notNull(),
expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at')
});
export const rateLimit = pgTable("rate_limit", {
id: text("id").primaryKey(),
key: text('key'),
count: integer('count'),
lastRequest: integer('last_request')
});

56
src/db/schema/auth.ts Normal file
View file

@ -0,0 +1,56 @@
import { text, integer, timestamp, boolean, pgSchema } from "drizzle-orm/pg-core";
export const authSchema = pgSchema('auth');
export const user = authSchema.table("user", {
id: text("id").primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
emailVerified: boolean('email_verified').notNull(),
image: text('image'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});
export const session = authSchema.table("session", {
id: text("id").primaryKey(),
expiresAt: timestamp('expires_at').notNull(),
token: text('token').notNull().unique(),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
ipAddress: text('ip_address'),
userAgent: text('user_agent'),
userId: text('user_id').notNull().references(() => user.id)
});
export const account = authSchema.table("account", {
id: text("id").primaryKey(),
accountId: text('account_id').notNull(),
providerId: text('provider_id').notNull(),
userId: text('user_id').notNull().references(() => user.id),
accessToken: text('access_token'),
refreshToken: text('refresh_token'),
idToken: text('id_token'),
accessTokenExpiresAt: timestamp('access_token_expires_at'),
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
scope: text('scope'),
password: text('password'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});
export const verification = authSchema.table("verification", {
id: text("id").primaryKey(),
identifier: text('identifier').notNull(),
value: text('value').notNull(),
expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at')
});
export const rateLimit = authSchema.table("rate_limit", {
id: text("id").primaryKey(),
key: text('key'),
count: integer('count'),
lastRequest: integer('last_request')
});

13
src/db/schema/note.ts Normal file
View file

@ -0,0 +1,13 @@
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { createId } from '@paralleldrive/cuid2'
import { user } from "./auth";
export const note = pgTable("note", {
id: text("id").primaryKey().$defaultFn(()=> `note_${createId()}`),
title: text("title"),
content: text("content"),
createdAt: timestamp().notNull().defaultNow(),
updatedAt: timestamp(),
deletedAt: timestamp(),
ownerId: text().notNull().references(() => user.id)
})

View file

@ -3,9 +3,8 @@ import { swagger } from "@elysiajs/swagger";
import { opentelemetry } from "@elysiajs/opentelemetry"; import { opentelemetry } from "@elysiajs/opentelemetry";
import { serverTiming } from "@elysiajs/server-timing"; import { serverTiming } from "@elysiajs/server-timing";
import { cors } from '@elysiajs/cors' import { cors } from '@elysiajs/cors'
import { note } from "./api/note/note.route"; import { noteRouter } from "./api/note/note.route";
import { betterAuthView } from "./lib/auth/auth-view"; import { betterAuthView } from "./lib/auth/auth-view";
import { userMiddleware, userInfo } from "./middlewares/auth-middleware";
import { getBaseConfig, validateEnv } from "./lib/utils/env"; import { getBaseConfig, validateEnv } from "./lib/utils/env";
const baseConfig = getBaseConfig() const baseConfig = getBaseConfig()
@ -23,10 +22,8 @@ const app = new Elysia()
if (code === "NOT_FOUND") return "Not Found :("; if (code === "NOT_FOUND") return "Not Found :(";
console.error(error); console.error(error);
}) })
.derive(({ request }) => userMiddleware(request))
.all("/api/auth/*", betterAuthView) .all("/api/auth/*", betterAuthView)
.use(note) .use(noteRouter)
.get("/user", ({ user, session }) => userInfo(user, session))
.get("/", () => `${baseConfig.SERVICE_NAME} Server is Running`) .get("/", () => `${baseConfig.SERVICE_NAME} Server is Running`)
validateEnv(); validateEnv();

View file

@ -2,7 +2,7 @@ import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "../../db/index"; import { db } from "../../db/index";
import { openAPI } from "better-auth/plugins" import { openAPI } from "better-auth/plugins"
import { user, account, verification, session } from "../../db/schema"; import { user, account, verification, session, rateLimit } from "../../db/schema/auth";
import { sendMail } from "../mail/mail"; import { sendMail } from "../mail/mail";
import { renderToStaticMarkup } from "react-dom/server"; import { renderToStaticMarkup } from "react-dom/server";
import { createElement } from "react"; import { createElement } from "react";
@ -15,7 +15,8 @@ export const auth = betterAuth({
user: user, user: user,
session: session, session: session,
account: account, account: account,
verification: verification verification: verification,
rateLimit: rateLimit,
} }
}), }),
rateLimit: { rateLimit: {

82
src/lib/utils/common.ts Normal file
View file

@ -0,0 +1,82 @@
import { t } from "elysia";
export const commonResponses = {
400: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Bad Request" }),
error: t.String({
default: "Missing parameters, or invalid parameters.",
}),
},
{
description:
"Bad Request. Usually due to missing parameters, or invalid parameters.",
}
),
401: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Unauthorized" }),
error: t.String({
default: "User needs to sign in to access this resource",
}),
},
{
description: "Unauthorized. Due to missing or invalid authentication.",
}
),
403: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Forbidden" }),
error: t.String({
default: "User does not have permission to access this resource",
}),
},
{
description:
"Forbidden. You do not have permission to access this resource or to perform this action.",
}
),
404: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Not Found" }),
error: t.String({ default: "Requested resource has not found" }),
},
{
description: "Not Found. The requested resource was not found.",
}
),
429: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Too Many Requests" }),
error: t.String({
default: "RUser has exceeded the rate limit. Try again later.",
}),
},
{
description:
"Too Many Requests. You have exceeded the rate limit. Try again later.",
}
),
500: t.Object(
{
data: t.Null(),
success: t.Boolean({ default: false }),
message: t.String({ default: "Internal Server Error" }),
error: t.String({ default: "Server faced an error" }),
},
{
description:
"Internal Server Error. This is a problem with the server that you cannot fix.",
}
),
};

View file

@ -1,15 +1,13 @@
import { Session, User } from "better-auth/types"; import { Session, User } from "better-auth/types";
import { auth } from "../lib/auth/auth"; import { auth } from "../lib/auth/auth";
import { error } from "elysia";
// user middleware (compute user and session and pass to routes) // user middleware (compute user and session and pass to routes)
export const userMiddleware = async (request: Request) => { export const userMiddleware = async (request: Request) => {
const session = await auth.api.getSession({ headers: request.headers }); const session = await auth.api.getSession({ headers: request.headers });
if (!session) { if (!session) {
return { return error("Unauthorized", 401);
user: null,
session: null,
};
} }
return { return {