Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f552894
update: docs path
samTime101 Sep 22, 2025
11fc58c
feat: added parameter validation
samTime101 Sep 22, 2025
522e940
refactor: removed parser and added body validation in route directly
samTime101 Sep 24, 2025
945b6f9
Merge pull request #48 from samTime101/feat/event/params
adgator101 Sep 24, 2025
c75737d
feat: add avatar_url column to members table and update member model
Kushal096 Sep 24, 2025
7b92f99
feat: implement image upload functionality to Cloudinary
Kushal096 Sep 24, 2025
8ed3a7c
feat: add image upload support and avatar URL handling in member crea…
Kushal096 Sep 24, 2025
c8ae4dd
Merge branch 'develop' of https://github.com/Kushal096/devsphere-back…
Kushal096 Sep 24, 2025
240bb3f
Merge pull request #50 from Kushal096/develop
Aayush0966 Sep 24, 2025
5c8f151
feat: add audit logging and enhance request context management
Aayush0966 Sep 25, 2025
4bdb3fd
update: added new env vars
samTime101 Sep 25, 2025
92ce891
fix: set github envs to optional
samTime101 Sep 25, 2025
bee0dcc
fix: skip env checks for github-actions
samTime101 Sep 25, 2025
f06e1ae
skip members test for now
samTime101 Sep 25, 2025
bdde720
fix: no manual setting for env for 'tests'
samTime101 Sep 25, 2025
2f2d604
add: GITHUB_TOKEN in env example
samTime101 Sep 25, 2025
55545d2
Merge pull request #51 from samTime101/optional/envs
Aayush0966 Sep 26, 2025
ce627ab
fix(audit): resolve middleware execution issues and prevent recursion
Aayush0966 Sep 26, 2025
c4fe5c2
feat: cloudinary integration on events (refactors & jsdocs)
samTime101 Sep 26, 2025
59bd69b
Merge branch 'develop' into feat/events/images
samTime101 Sep 26, 2025
cdfc30e
fix: seperate saving of images on seperate folders not nested
samTime101 Sep 26, 2025
4f36c57
refractor(audit): improve code readability and add comments
Aayush0966 Sep 26, 2025
efb9623
Merge pull request #53 from samTime101/feat/events/images
Aayush0966 Sep 26, 2025
b443dbd
Merge branch 'BIC-DevSphere:develop' into develop
Aayush0966 Sep 26, 2025
beacb01
feat(audit): add fetch audits controller and services
Aayush0966 Sep 26, 2025
3e54f09
Merge pull request #52 from Aayush0966/develop
adgator101 Sep 27, 2025
ac8d0dd
fix(audit): add a entity check to only check for defined models
Aayush0966 Sep 27, 2025
29f64ba
fix(auth): add checks for user conflicts
Aayush0966 Sep 27, 2025
2758532
Merge pull request #54 from Aayush0966/develop
adgator101 Sep 28, 2025
97a1b62
feat(project): enhance project creation and update with thumbnail sup…
adgator101 Sep 28, 2025
2c8b1d5
feat(tag): implement updateProjectTags method to manage tag associations
adgator101 Sep 28, 2025
a6e2bd0
refactor(project): remove commented-out code for tag management in up…
adgator101 Sep 28, 2025
a3e797d
feat(audit): add auditlogs migration files
Aayush0966 Sep 28, 2025
c253c07
Merge pull request #57 from Aayush0966/develop
adgator101 Sep 28, 2025
bd25b1f
Merge branch 'BIC-DevSphere:develop' into develop
adgator101 Sep 28, 2025
a909ffd
Merge pull request #56 from adgator101/develop
Aayush0966 Sep 28, 2025
2833c3f
feat: fully working event update with additional refactoring to overa…
samTime101 Sep 27, 2025
26d452d
todo(done): folder removal cloudinary
samTime101 Sep 28, 2025
7269fdb
Merge pull request #55 from samTime101/refactor/event/update
adgator101 Sep 29, 2025
1823a72
feat(database): add unique constraints to contributors and project_co…
adgator101 Sep 29, 2025
b371ddc
Merge branch 'develop' of github.com:adgator101/devsphere-backend int…
adgator101 Sep 29, 2025
03b9e01
feat(migration): drop 'deleted_at' column and add 'public_id' to even…
adgator101 Sep 29, 2025
366b07c
Merge pull request #58 from adgator101/develop
adgator101 Sep 29, 2025
bf979c5
feat(dependencies): add prettier and node-cron to package.json and pa…
adgator101 Sep 29, 2025
8d702ee
feat(contributor): enhance contributor fetching and existence checkin…
adgator101 Sep 29, 2025
4998b5b
refactor(project): improve error handling and use updated method from…
adgator101 Sep 29, 2025
8ac4f2f
feat(contributor): add contributor cron job to fetch and update GitHu…
adgator101 Sep 29, 2025
a56a9aa
Merge pull request #59 from adgator101/develop
Aayush0966 Sep 29, 2025
2d9981a
feat(docs): add workflow documentation for contributor cron job
adgator101 Sep 30, 2025
11ae391
feat(docs): update README and CONTRIBUTING files for clarity and impr…
adgator101 Sep 30, 2025
1eee52d
Merge pull request #60 from adgator101/develop
Aayush0966 Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ BETTER_AUTH_URL=
NODE_ENV=
JWT_ACCESS_SECRET=
JWT_REFRESH_SECRET=
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
GITHUB_SECRET=
GITHUB_CLIENT_ID=
GITHUB_TOKEN=
11 changes: 11 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}
216 changes: 96 additions & 120 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,6 @@ Welcome to the DevSphere Backend project! This guide will help you understand ou
- [Authentication & Authorization](#authentication--authorization)
- [Code Style Guidelines](#code-style-guidelines)

## Getting Started

### Prerequisites
- Node.js (v18+)
- PostgreSQL database
- npm or yarn package manager

### Setup
1. Clone the repository
2. Install dependencies: `npm install`
3. Set up environment variables (see `.env.example`)
4. Generate Prisma client: `npm run generate`
5. Run migrations: `npm run migrate`
6. Start development server: `npm run dev`

## Project Structure

```
Expand All @@ -44,7 +29,7 @@ src/
├── utils/ # Utility functions and constants
├── types/ # TypeScript type definitions
├── dtos/ # Data Transfer Objects for responses
├── parser/ # Input validation and parsing logic
├── jobs/ # Background jobs and cron tasks
├── db/ # Database configuration
└── index.ts # Application entry point

Expand All @@ -58,14 +43,17 @@ docs/ # API documentation
## Naming Conventions

### File Naming

- Use **kebab-case** for file names: `event.controller.ts`, `member.service.ts`
- Use **camelCase** for directories: `controllers/`, `services/`

### Class Naming

- Use **PascalCase** for class names: `EventController`, `MemberService`
- Export instances using **camelCase**: `export const eventController = new EventController()`

### Function Naming

- Use **camelCase** for function names: `createEvent`, `getUserRole`
- Use descriptive verbs for CRUD operations:
- `create` for POST operations
Expand All @@ -74,6 +62,7 @@ docs/ # API documentation
- `remove`/`delete` for DELETE operations

### Variable Naming

- Use **camelCase** for variables: `eventData`, `userId`
- Use **SCREAMING_SNAKE_CASE** for constants: `HTTP.INTERNAL`, `DATABASE_URL`

Expand Down Expand Up @@ -103,34 +92,34 @@ Services contain the core business logic and database operations. They follow a
### Service Class Structure

```typescript
import prisma from "@/db/prisma";
import { prismaSafe } from "@/lib/prismaSafe";
import prisma from '@/db/prisma';
import { prismaSafe } from '@/lib/prismaSafe';

class ExampleService {
async createExample(data: ExampleType) {
try {
const [dbError, result] = await prismaSafe(
prisma.example.create({
data: {
...data
}
})
);

if (dbError) {
return { success: false, error: dbError };
}

if (!result) {
return { success: false, error: 'Failed to create example' };
}

return { success: true, data: result };
} catch (error) {
console.log(`Failed to create example: ${error}`);
return { success: false, error: 'Failed to create example' };
}
async createExample(data: ExampleType) {
try {
const [dbError, result] = await prismaSafe(
prisma.example.create({
data: {
...data,
},
})
);

if (dbError) {
return { success: false, error: dbError };
}

if (!result) {
return { success: false, error: 'Failed to create example' };
}

return { success: true, data: result };
} catch (error) {
console.log(`Failed to create example: ${error}`);
return { success: false, error: 'Failed to create example' };
}
}
}

export const exampleService = new ExampleService();
Expand All @@ -143,48 +132,51 @@ export const exampleService = new ExampleService();
- `update{Resource}` - Update existing resource
- `remove{Resource}` or `delete{Resource}` - Delete resource

### Method Organization

- **Public methods at the top**
- **Private helpers at the bottom** (prefixed with `_`)

## Controller Layer Conventions

Controllers handle HTTP requests, validate input, call services, and return responses.

### Controller Structure

```typescript
import type { Request, Response } from "express";
import type { Request, Response } from 'express';
import { ErrorResponse, SuccessResponse } from '@/dtos';
import { HTTP } from '@/utils/constants';
import { exampleService } from '@/services/example.service';
import exampleParser from '@/parser/example/example.parser';

class ExampleController {
async createExample(req: Request, res: Response) {
try {
// 1. Parse and validate input
const parseResult = await exampleParser(req.body);
if (!parseResult.success) {
return res.status(HTTP.BAD_REQUEST).json(
ErrorResponse(HTTP.BAD_REQUEST, parseResult.error || 'Invalid data')
);
}

// 2. Call service
const serviceResult = await exampleService.createExample(parseResult.data);
if (!serviceResult.success) {
return res.status(HTTP.INTERNAL).json(
ErrorResponse(HTTP.INTERNAL, serviceResult.error || 'Failed to create')
);
}

// 3. Return success response
return res.status(HTTP.CREATED).json(
SuccessResponse(HTTP.CREATED, 'Created successfully', serviceResult.data)
);
} catch (error) {
return res.status(HTTP.INTERNAL).json(
ErrorResponse(HTTP.INTERNAL, 'Internal Server Error')
);
}
async createExample(req: Request, res: Response) {
try {
// 1. Parse and validate input
const parseResult = await exampleParser(req.body);
if (!parseResult.success) {
return res
.status(HTTP.BAD_REQUEST)
.json(ErrorResponse(HTTP.BAD_REQUEST, parseResult.error || 'Invalid data'));
}

// 2. Call service
const serviceResult = await exampleService.createExample(parseResult.data);
if (!serviceResult.success) {
return res
.status(HTTP.INTERNAL)
.json(ErrorResponse(HTTP.INTERNAL, serviceResult.error || 'Failed to create'));
}

// 3. Return success response
return res
.status(HTTP.CREATED)
.json(SuccessResponse(HTTP.CREATED, 'Created successfully', serviceResult.data));
} catch (error) {
return res.status(HTTP.INTERNAL).json(ErrorResponse(HTTP.INTERNAL, 'Internal Server Error'));
}
}
}

export const exampleController = new ExampleController();
Expand Down Expand Up @@ -213,10 +205,6 @@ Routes should be organized by resource and follow RESTful conventions.
### Route File Structure

```typescript
import { Router } from 'express';
import { exampleController } from '@/controllers/example.controller';
import { authMiddleware, isAdmin } from '@/middleware/auth.middleware';

const exampleRouter = Router();

// Public routes
Expand All @@ -236,14 +224,14 @@ export default exampleRouter;

### RESTful Route Conventions

| HTTP Method | Route Pattern | Purpose | Controller Method |
|-------------|---------------|---------|-------------------|
| `GET` | `/api/resource` | Get all resources | `getResources` |
| `GET` | `/api/resource/:id` | Get single resource | `getResource` |
| `POST` | `/api/resource` | Create new resource | `createResource` |
| `PUT` | `/api/resource/:id` | Update entire resource | `updateResource` |
| `PATCH` | `/api/resource/:id` | Partial update | `patchResource` |
| `DELETE` | `/api/resource/:id` | Delete resource | `deleteResource` |
| HTTP Method | Route Pattern | Purpose | Controller Method |
| ----------- | ------------------- | ---------------------- | ----------------- |
| `GET` | `/api/resource` | Get all resources | `getResources` |
| `GET` | `/api/resource/:id` | Get single resource | `getResource` |
| `POST` | `/api/resource` | Create new resource | `createResource` |
| `PUT` | `/api/resource/:id` | Update entire resource | `updateResource` |
| `PATCH` | `/api/resource/:id` | Partial update | `patchResource` |
| `DELETE` | `/api/resource/:id` | Delete resource | `deleteResource` |

### Route Registration in Main App

Expand All @@ -260,30 +248,15 @@ app.use('/api/members', memberRouter);

Use the constants from `@/utils/constants`:

```typescript
export const HTTP = {
OK: 200,
CREATED: 201,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
CONFLICT: 409,
INTERNAL: 500,
} as const;
```

### Database Error Handling

Always use `prismaSafe` for database operations:

```typescript
const [error, result] = await prismaSafe(
prisma.model.operation()
);
const [error, result] = await prismaSafe(prisma.model.operation());

if (error) {
return { success: false, error };
return { success: false, error };
}
```

Expand All @@ -297,25 +270,26 @@ if (error) {

```typescript
const [error, user] = await prismaSafe(
prisma.user.findUnique({
where: { id: userId }
})
prisma.user.findUnique({
where: { id: userId },
})
);

if (error) {
return { success: false, error };
return { success: false, error };
}

if (!user) {
return { success: false, error: 'User not found' };
return { success: false, error: 'User not found' };
}
```

### Schema Changes

After any Prisma schema changes:
1. Run `npm run push` to update the database
2. Run `npm run generate` to update the Prisma client

1. Run `npx prisma migrate dev` to update the database
2. Run `npx prisma generate` to update the Prisma client

## Type Definitions

Expand All @@ -328,15 +302,15 @@ After any Prisma schema changes:
```typescript
// src/types/example.types.ts
export interface Example {
id: string;
name: string;
createdAt: Date;
updatedAt: Date;
id: string;
name: string;
createdAt: Date;
updatedAt: Date;
}

export interface CreateExampleRequest {
name: string;
description?: string;
name: string;
description?: string;
}
```

Expand All @@ -347,16 +321,19 @@ Place validation schemas in `src/utils/types/`:
```typescript
import { z } from 'zod';

export const exampleSchema = z.object({
name: z.string().min(1, "Name is required"),
export const exampleSchema = z
.object({
name: z.string().min(1, 'Name is required'),
description: z.string().optional(),
}).strict();
})
.strict();

export type Example = z.infer<typeof exampleSchema>;
```

## Validation & Parsing
use Zod validation middleware

use Zod validation middleware

## Authentication & Authorization

Expand Down Expand Up @@ -420,11 +397,10 @@ import { exampleService } from '@/services/example.service';

## Pull Request Guidelines

1. **Create feature branches** from `main`
2. **Write descriptive commit messages**
3. **Test your changes** thoroughly
4. **Update documentation** if needed
5. **Follow all conventions** outlined in this guide
1. **Write descriptive commit messages**
2. **Test your changes** thoroughly
3. **Update documentation** if needed
4. **Follow all conventions** outlined in this guide

### Commit Message Format

Expand Down
Loading
Loading