@@ -17,21 +17,6 @@ Welcome to the DevSphere Backend project! This guide will help you understand ou
1717- [ Authentication & Authorization] ( #authentication--authorization )
1818- [ Code Style Guidelines] ( #code-style-guidelines )
1919
20- ## Getting Started
21-
22- ### Prerequisites
23- - Node.js (v18+)
24- - PostgreSQL database
25- - npm or yarn package manager
26-
27- ### Setup
28- 1 . Clone the repository
29- 2 . Install dependencies: ` npm install `
30- 3 . Set up environment variables (see ` .env.example ` )
31- 4 . Generate Prisma client: ` npm run generate `
32- 5 . Run migrations: ` npm run migrate `
33- 6 . Start development server: ` npm run dev `
34-
3520## Project Structure
3621
3722```
4429├── utils/ # Utility functions and constants
4530├── types/ # TypeScript type definitions
4631├── dtos/ # Data Transfer Objects for responses
47- ├── parser / # Input validation and parsing logic
32+ ├── jobs / # Background jobs and cron tasks
4833├── db/ # Database configuration
4934└── index.ts # Application entry point
5035
@@ -58,14 +43,17 @@ docs/ # API documentation
5843## Naming Conventions
5944
6045### File Naming
46+
6147- Use ** kebab-case** for file names: ` event.controller.ts ` , ` member.service.ts `
6248- Use ** camelCase** for directories: ` controllers/ ` , ` services/ `
6349
6450### Class Naming
51+
6552- Use ** PascalCase** for class names: ` EventController ` , ` MemberService `
6653- Export instances using ** camelCase** : ` export const eventController = new EventController() `
6754
6855### Function Naming
56+
6957- Use ** camelCase** for function names: ` createEvent ` , ` getUserRole `
7058- Use descriptive verbs for CRUD operations:
7159 - ` create ` for POST operations
@@ -74,6 +62,7 @@ docs/ # API documentation
7462 - ` remove ` /` delete ` for DELETE operations
7563
7664### Variable Naming
65+
7766- Use ** camelCase** for variables: ` eventData ` , ` userId `
7867- Use ** SCREAMING_SNAKE_CASE** for constants: ` HTTP.INTERNAL ` , ` DATABASE_URL `
7968
@@ -103,34 +92,34 @@ Services contain the core business logic and database operations. They follow a
10392### Service Class Structure
10493
10594``` typescript
106- import prisma from " @/db/prisma" ;
107- import { prismaSafe } from " @/lib/prismaSafe" ;
95+ import prisma from ' @/db/prisma' ;
96+ import { prismaSafe } from ' @/lib/prismaSafe' ;
10897
10998class ExampleService {
110- async createExample(data : ExampleType ) {
111- try {
112- const [dbError, result] = await prismaSafe (
113- prisma .example .create ({
114- data: {
115- ... data
116- }
117- })
118- );
119-
120- if (dbError ) {
121- return { success: false , error: dbError };
122- }
123-
124- if (! result ) {
125- return { success: false , error: ' Failed to create example' };
126- }
127-
128- return { success: true , data: result };
129- } catch (error ) {
130- console .log (` Failed to create example: ${error } ` );
131- return { success: false , error: ' Failed to create example' };
132- }
99+ async createExample(data : ExampleType ) {
100+ try {
101+ const [dbError, result] = await prismaSafe (
102+ prisma .example .create ({
103+ data: {
104+ ... data ,
105+ },
106+ })
107+ );
108+
109+ if (dbError ) {
110+ return { success: false , error: dbError };
111+ }
112+
113+ if (! result ) {
114+ return { success: false , error: ' Failed to create example' };
115+ }
116+
117+ return { success: true , data: result };
118+ } catch (error ) {
119+ console .log (` Failed to create example: ${error } ` );
120+ return { success: false , error: ' Failed to create example' };
133121 }
122+ }
134123}
135124
136125export const exampleService = new ExampleService ();
@@ -143,48 +132,51 @@ export const exampleService = new ExampleService();
143132- ` update{Resource} ` - Update existing resource
144133- ` remove{Resource} ` or ` delete{Resource} ` - Delete resource
145134
135+ ### Method Organization
136+
137+ - ** Public methods at the top**
138+ - ** Private helpers at the bottom** (prefixed with ` _ ` )
139+
146140## Controller Layer Conventions
147141
148142Controllers handle HTTP requests, validate input, call services, and return responses.
149143
150144### Controller Structure
151145
152146``` typescript
153- import type { Request , Response } from " express" ;
147+ import type { Request , Response } from ' express' ;
154148import { ErrorResponse , SuccessResponse } from ' @/dtos' ;
155149import { HTTP } from ' @/utils/constants' ;
156150import { exampleService } from ' @/services/example.service' ;
157151import exampleParser from ' @/parser/example/example.parser' ;
158152
159153class ExampleController {
160- async createExample(req : Request , res : Response ) {
161- try {
162- // 1. Parse and validate input
163- const parseResult = await exampleParser (req .body );
164- if (! parseResult .success ) {
165- return res .status (HTTP .BAD_REQUEST ).json (
166- ErrorResponse (HTTP .BAD_REQUEST , parseResult .error || ' Invalid data' )
167- );
168- }
169-
170- // 2. Call service
171- const serviceResult = await exampleService .createExample (parseResult .data );
172- if (! serviceResult .success ) {
173- return res .status (HTTP .INTERNAL ).json (
174- ErrorResponse (HTTP .INTERNAL , serviceResult .error || ' Failed to create' )
175- );
176- }
177-
178- // 3. Return success response
179- return res .status (HTTP .CREATED ).json (
180- SuccessResponse (HTTP .CREATED , ' Created successfully' , serviceResult .data )
181- );
182- } catch (error ) {
183- return res .status (HTTP .INTERNAL ).json (
184- ErrorResponse (HTTP .INTERNAL , ' Internal Server Error' )
185- );
186- }
154+ async createExample(req : Request , res : Response ) {
155+ try {
156+ // 1. Parse and validate input
157+ const parseResult = await exampleParser (req .body );
158+ if (! parseResult .success ) {
159+ return res
160+ .status (HTTP .BAD_REQUEST )
161+ .json (ErrorResponse (HTTP .BAD_REQUEST , parseResult .error || ' Invalid data' ));
162+ }
163+
164+ // 2. Call service
165+ const serviceResult = await exampleService .createExample (parseResult .data );
166+ if (! serviceResult .success ) {
167+ return res
168+ .status (HTTP .INTERNAL )
169+ .json (ErrorResponse (HTTP .INTERNAL , serviceResult .error || ' Failed to create' ));
170+ }
171+
172+ // 3. Return success response
173+ return res
174+ .status (HTTP .CREATED )
175+ .json (SuccessResponse (HTTP .CREATED , ' Created successfully' , serviceResult .data ));
176+ } catch (error ) {
177+ return res .status (HTTP .INTERNAL ).json (ErrorResponse (HTTP .INTERNAL , ' Internal Server Error' ));
187178 }
179+ }
188180}
189181
190182export const exampleController = new ExampleController ();
@@ -213,10 +205,6 @@ Routes should be organized by resource and follow RESTful conventions.
213205### Route File Structure
214206
215207` ` ` typescript
216- import { Router } from ' express' ;
217- import { exampleController } from ' @/controllers/example.controller' ;
218- import { authMiddleware , isAdmin } from ' @/middleware/auth.middleware' ;
219-
220208const exampleRouter = Router ();
221209
222210// Public routes
@@ -236,14 +224,14 @@ export default exampleRouter;
236224
237225### RESTful Route Conventions
238226
239- | HTTP Method | Route Pattern | Purpose | Controller Method |
240- |-------------| ---------------| ---------| -------------------|
241- | ` GET ` | ` / api / resource ` | Get all resources | ` getResources ` |
242- | ` GET ` | ` / api / resource / : id ` | Get single resource | ` getResource ` |
243- | ` POST ` | ` / api / resource ` | Create new resource | ` createResource ` |
244- | ` PUT ` | ` / api / resource / :id ` | Update entire resource | ` updateResource ` |
245- | ` PATCH ` | ` / api / resource / :id ` | Partial update | ` patchResource ` |
246- | ` DELETE ` | ` / api / resource / :id ` | Delete resource | ` deleteResource ` |
227+ | HTTP Method | Route Pattern | Purpose | Controller Method |
228+ | ----------- | -- ----------------- | ---------------------- | ----------------- |
229+ | ` GET ` | ` / api / resource ` | Get all resources | ` getResources ` |
230+ | ` GET ` | ` / api / resource / : id ` | Get single resource | ` getResource ` |
231+ | ` POST ` | ` / api / resource ` | Create new resource | ` createResource ` |
232+ | ` PUT ` | ` / api / resource / :id ` | Update entire resource | ` updateResource ` |
233+ | ` PATCH ` | ` / api / resource / :id ` | Partial update | ` patchResource ` |
234+ | ` DELETE ` | ` / api / resource / :id ` | Delete resource | ` deleteResource ` |
247235
248236### Route Registration in Main App
249237
@@ -260,30 +248,15 @@ app.use('/api/members', memberRouter);
260248
261249Use the constants from ` @/ utils / constants ` :
262250
263- ` ` ` typescript
264- export const HTTP = {
265- OK: 200 ,
266- CREATED: 201 ,
267- BAD_REQUEST: 400 ,
268- UNAUTHORIZED: 401 ,
269- FORBIDDEN: 403 ,
270- NOT_FOUND: 404 ,
271- CONFLICT: 409 ,
272- INTERNAL: 500 ,
273- } as const ;
274- ` ` `
275-
276251### Database Error Handling
277252
278253Always use ` prismaSafe ` for database operations:
279254
280255` ` ` typescript
281- const [error , result ] = await prismaSafe (
282- prisma .model .operation ()
283- );
256+ const [error , result ] = await prismaSafe (prisma .model .operation ());
284257
285258if (error ) {
286- return { success : false , error };
259+ return { success : false , error };
287260}
288261` ` `
289262
@@ -297,25 +270,26 @@ if (error) {
297270
298271` ` ` typescript
299272const [error , user ] = await prismaSafe (
300- prisma .user .findUnique ({
301- where: { id: userId }
302- })
273+ prisma .user .findUnique ({
274+ where: { id: userId },
275+ })
303276);
304277
305278if (error ) {
306- return { success : false , error };
279+ return { success : false , error };
307280}
308281
309282if (! user ) {
310- return { success : false , error : ' User not found' };
283+ return { success : false , error : ' User not found' };
311284}
312285` ` `
313286
314287### Schema Changes
315288
316289After any Prisma schema changes:
317- 1. Run ` npm run push ` to update the database
318- 2. Run ` npm run generate ` to update the Prisma client
290+
291+ 1. Run ` npx prisma migrate dev ` to update the database
292+ 2. Run ` npx prisma generate ` to update the Prisma client
319293
320294## Type Definitions
321295
@@ -328,15 +302,15 @@ After any Prisma schema changes:
328302` ` ` typescript
329303// src/types/example.types.ts
330304export interface Example {
331- id: string ;
332- name : string ;
333- createdAt : Date ;
334- updatedAt : Date ;
305+ id: string ;
306+ name : string ;
307+ createdAt : Date ;
308+ updatedAt : Date ;
335309}
336310
337311export interface CreateExampleRequest {
338- name: string ;
339- description ?: string ;
312+ name: string ;
313+ description ?: string ;
340314}
341315` ` `
342316
@@ -347,16 +321,19 @@ Place validation schemas in `src/utils/types/`:
347321` ` ` typescript
348322import { z } from ' zod' ;
349323
350- export const exampleSchema = z .object ({
351- name: z .string ().min (1 , " Name is required" ),
324+ export const exampleSchema = z
325+ .object ({
326+ name: z .string ().min (1 , ' Name is required' ),
352327 description: z .string ().optional (),
353- }).strict ();
328+ })
329+ .strict ();
354330
355331export type Example = z .infer < typeof exampleSchema > ;
356332` ` `
357333
358334## Validation & Parsing
359- use Zod validation middleware
335+
336+ use Zod validation middleware
360337
361338## Authentication & Authorization
362339
@@ -420,11 +397,10 @@ import { exampleService } from '@/services/example.service';
420397
421398## Pull Request Guidelines
422399
423- 1. **Create feature branches** from ` main `
424- 2. **Write descriptive commit messages**
425- 3. **Test your changes** thoroughly
426- 4. **Update documentation** if needed
427- 5. **Follow all conventions** outlined in this guide
400+ 1. **Write descriptive commit messages**
401+ 2. **Test your changes** thoroughly
402+ 3. **Update documentation** if needed
403+ 4. **Follow all conventions** outlined in this guide
428404
429405### Commit Message Format
430406
0 commit comments