now we only need tests

This commit is contained in:
Sanjib Sen 2025-01-16 15:50:28 +06:00
parent 443b19c7c0
commit 21308fa5bd
7 changed files with 48 additions and 52 deletions

View file

@ -59,8 +59,9 @@ CREATE TABLE "note" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"title" text, "title" text,
"content" text, "content" text,
"createdAt" timestamp DEFAULT now(), "createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp, "updatedAt" timestamp,
"deletedAt" timestamp,
"ownerId" text NOT NULL "ownerId" text NOT NULL
); );
--> statement-breakpoint --> statement-breakpoint

View file

@ -1,5 +1,5 @@
{ {
"id": "806f9895-fec6-43da-9c78-46e599e611e8", "id": "50bd2c27-8d45-478f-a894-b2f7cd4a718b",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
@ -369,7 +369,7 @@
"name": "createdAt", "name": "createdAt",
"type": "timestamp", "type": "timestamp",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": true,
"default": "now()" "default": "now()"
}, },
"updatedAt": { "updatedAt": {
@ -378,6 +378,12 @@
"primaryKey": false, "primaryKey": false,
"notNull": false "notNull": false
}, },
"deletedAt": {
"name": "deletedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"ownerId": { "ownerId": {
"name": "ownerId", "name": "ownerId",
"type": "text", "type": "text",

View file

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

View file

@ -5,11 +5,13 @@
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"dev": "bun run --watch src/index.ts", "dev": "bun run --watch src/index.ts",
"email": "email dev --dir src/emails", "email": "email dev --dir src/emails",
"auth:generate": "bun x @better-auth/cli generate --config src/lib/auth/auth.ts --output src/db/schema/auth.ts && drizzle-kit migrate",
"db:studio": "drizzle-kit studio", "db:studio": "drizzle-kit studio",
"auth:generate": "bun x @better-auth/cli generate --config src/lib/auth/auth.ts --output src/db/schema.ts && drizzle-kit migrate",
"db:check": "drizzle-kit check", "db:check": "drizzle-kit check",
"db:generate": "drizzle-kit generate", "db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate", "db:migrate": "drizzle-kit migrate",
"db:pull": "drizzle-kit pull",
"db:push": "drizzle-kit push",
"build": "bun build --compile --minify-whitespace --minify-syntax --target bun --outfile server ./src/index.ts" "build": "bun build --compile --minify-whitespace --minify-syntax --target bun --outfile server ./src/index.ts"
}, },
"dependencies": { "dependencies": {

View file

@ -1,10 +1,10 @@
import { and, eq, notExists } from "drizzle-orm"; import { and, eq, isNull } from "drizzle-orm";
import { db } from "../../../db"; import { db } from "../../../db";
import { note } from "../../../db/schema/note"; import { note } from "../../../db/schema/note";
import { CreateNote } from "./note.model"; import { CreateNoteType } from "./note.model";
export class NoteController { export class NoteController {
async createNote(new_note: CreateNote, ownerId: string) { async createNote(new_note: CreateNoteType, ownerId: string) {
const new_note_data = { ...new_note, ownerId: ownerId }; const new_note_data = { ...new_note, ownerId: ownerId };
const result = await db const result = await db
.insert(note) .insert(note)
@ -35,7 +35,7 @@ export class NoteController {
updatedAt: note.updatedAt, updatedAt: note.updatedAt,
}) })
.from(note) .from(note)
.where(and(eq(note.ownerId, ownerId), notExists(note.deletedAt))) .where(and(eq(note.ownerId, ownerId), isNull(note.deletedAt)))
.limit(limit).offset(offset) .limit(limit).offset(offset)
.execute(); .execute();
return { return {
@ -60,7 +60,7 @@ export class NoteController {
and( and(
eq(note.id, noteId), eq(note.id, noteId),
eq(note.ownerId, ownerId), eq(note.ownerId, ownerId),
notExists(note.deletedAt) isNull(note.deletedAt)
) )
) )
.execute(); .execute();
@ -74,7 +74,7 @@ export class NoteController {
async updateNoteById( async updateNoteById(
noteId: string, noteId: string,
updated_note: CreateNote, updated_note: CreateNoteType,
ownerId: string ownerId: string
) { ) {
const new_note_data = { ...updated_note, updatedAt: new Date() }; const new_note_data = { ...updated_note, updatedAt: new Date() };
@ -85,7 +85,7 @@ export class NoteController {
and( and(
eq(note.id, noteId), eq(note.id, noteId),
eq(note.ownerId, ownerId), eq(note.ownerId, ownerId),
notExists(note.deletedAt) isNull(note.deletedAt)
) )
) )
.returning({ .returning({
@ -113,7 +113,7 @@ export class NoteController {
and( and(
eq(note.id, noteId), eq(note.id, noteId),
eq(note.ownerId, ownerId), eq(note.ownerId, ownerId),
notExists(note.deletedAt) isNull(note.deletedAt)
) )
) )
.execute(); .execute();
@ -129,7 +129,7 @@ export class NoteController {
await db await db
.update(note) .update(note)
.set({ deletedAt: new Date() }) .set({ deletedAt: new Date() })
.where(and(eq(note.ownerId, ownerId), notExists(note.deletedAt))) .where(and(eq(note.ownerId, ownerId), isNull(note.deletedAt)))
.execute(); .execute();
return { return {
success: true, success: true,

View file

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

View file

@ -1,8 +1,7 @@
import { Elysia, error, t } from "elysia"; import { Elysia, t } from "elysia";
import { createNoteSchema, NoteSchema, successDeleteNoteResponse, successGetNoteResponse } from "./note.model"; import { createNoteSchema, deleteNoteResponses, getNoteResponses, NoteSchema } from "./note.model";
import { NoteController } from "./note.controller"; import { NoteController } from "./note.controller";
import { userMiddleware } from "../../../middlewares/auth-middleware"; import { userMiddleware } from "../../../middlewares/auth-middleware";
import { commonResponses } from "../../../lib/utils/common";
export const noteRouter = new Elysia({ export const noteRouter = new Elysia({
prefix: "/note", prefix: "/note",
@ -37,10 +36,7 @@ export const noteRouter = new Elysia({
limit: t.Optional(t.Number()), limit: t.Optional(t.Number()),
offset: t.Optional(t.Number()) offset: t.Optional(t.Number())
}), }),
response:{ response:getNoteResponses,
200: successGetNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Get all notes of the user", "description":"Get all notes of the user",
"summary":"Get all notes" "summary":"Get all notes"
@ -56,10 +52,7 @@ export const noteRouter = new Elysia({
params:t.Object({ params:t.Object({
id: t.String(), id: t.String(),
}), }),
response: { response: getNoteResponses,
200: successGetNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Get a note by Id", "description":"Get a note by Id",
"summary":"Get a note" "summary":"Get a note"
@ -73,10 +66,7 @@ export const noteRouter = new Elysia({
}, },
{ {
body: createNoteSchema, body: createNoteSchema,
response: { response: getNoteResponses,
200: successGetNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Create a new note", "description":"Create a new note",
"summary":"Create a note" "summary":"Create a note"
@ -92,10 +82,7 @@ export const noteRouter = new Elysia({
params:t.Object({ params:t.Object({
id: t.String(), id: t.String(),
}), }),
response: { response: getNoteResponses,
200: successGetNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Update a note by Id", "description":"Update a note by Id",
"summary":"Update a note" "summary":"Update a note"
@ -110,10 +97,7 @@ export const noteRouter = new Elysia({
params:t.Object({ params:t.Object({
id: t.String(), id: t.String(),
}), }),
response: { response: deleteNoteResponses,
200: successDeleteNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Delete a note by Id", "description":"Delete a note by Id",
"summary":"Delete a note" "summary":"Delete a note"
@ -126,10 +110,7 @@ export const noteRouter = new Elysia({
return await note.deleteAllNotes(user.id); return await note.deleteAllNotes(user.id);
}, },
{ {
response: { response: deleteNoteResponses,
200: successDeleteNoteResponse,
...commonResponses
},
detail:{ detail:{
"description":"Delete all notes of an user", "description":"Delete all notes of an user",
"summary":"Delete all notes" "summary":"Delete all notes"