Skip to content

Commit 9e91f37

Browse files
committed
init commit for project and project packages
1 parent 4c955f3 commit 9e91f37

8 files changed

+260
-4
lines changed
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// DTOs for Project APIs
2+
import { InputType, Field, ID } from '@nestjs/graphql';
3+
4+
@InputType()
5+
export class UpsertProjectInput {
6+
@Field()
7+
project_name: string;
8+
9+
@Field()
10+
path: string;
11+
12+
@Field(() => ID)
13+
user_id: string;
14+
15+
@Field(() => ID, { nullable: true })
16+
project_id: string;
17+
18+
// may need
19+
// @Field(() => [String])
20+
// project_packages: string[];
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ProjectPackages Module
2+
import { Module } from '@nestjs/common';
3+
import { TypeOrmModule } from '@nestjs/typeorm';
4+
import { ProjectPackages } from './project-packages.model';
5+
import { ProjectPackagesService } from './project-packages.service';
6+
import { ProjectPackagesResolver } from './project-packages.resolver';
7+
8+
@Module({
9+
imports: [TypeOrmModule.forFeature([ProjectPackages])],
10+
providers: [ProjectPackagesService, ProjectPackagesResolver],
11+
exports: [ProjectPackagesService],
12+
})
13+
export class ProjectPackagesModule {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// GraphQL Resolver for ProjectPackages APIs
2+
import { Resolver, Mutation, Args } from '@nestjs/graphql';
3+
import { ProjectPackagesService } from './project-packages.service';
4+
import { ProjectPackages } from './project-packages.model';
5+
6+
@Resolver(() => ProjectPackages)
7+
export class ProjectPackagesResolver {
8+
constructor(private readonly projectPackagesService: ProjectPackagesService) {}
9+
10+
@Mutation(() => ProjectPackages)
11+
async addPackageToProject(
12+
@Args('projectId') projectId: string,
13+
@Args('packageContent') packageContent: string
14+
): Promise<ProjectPackages> {
15+
return this.projectPackagesService.addPackageToProject(projectId, packageContent);
16+
}
17+
18+
@Mutation(() => Boolean)
19+
async removePackageFromProject(
20+
@Args('projectId') projectId: string,
21+
@Args('packageId') packageId: string
22+
): Promise<boolean> {
23+
return this.projectPackagesService.removePackageFromProject(projectId, packageId);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// ProjectPackages Service for managing Project Packages
2+
import { Injectable } from '@nestjs/common';
3+
import { InjectRepository } from '@nestjs/typeorm';
4+
import { Repository } from 'typeorm';
5+
import { ProjectPackages } from './project-packages.model';
6+
7+
@Injectable()
8+
export class ProjectPackagesService {
9+
constructor(
10+
@InjectRepository(ProjectPackages)
11+
private projectPackagesRepository: Repository<ProjectPackages>
12+
) {}
13+
14+
async addPackageToProject(projectId: string, packageContent: string): Promise<ProjectPackages> {
15+
const projectPackage = this.projectPackagesRepository.create({
16+
project_id: projectId,
17+
content: packageContent,
18+
});
19+
return await this.projectPackagesRepository.save(projectPackage);
20+
}
21+
22+
async removePackageFromProject(projectId: string, packageId: string): Promise<boolean> {
23+
const result = await this.projectPackagesRepository.delete({ id: packageId, project_id: projectId });
24+
return result.affected > 0;
25+
}
26+
}

backend/src/project/project.model.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ export class Projects extends SystemBaseModel {
3333
@ManyToOne(() => User)
3434
@JoinColumn({ name: 'user_id' })
3535
user: User;
36-
37-
@OneToMany(() => ProjectPackages, (projectPackage) => projectPackage.project)
36+
37+
@Field(() => [ProjectPackages], { nullable: true })
38+
@OneToMany(() => ProjectPackages, (projectPackage) => projectPackage.project, { cascade: true })
3839
projectPackages: ProjectPackages[];
3940
}

backend/src/project/project.module.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import { Module } from '@nestjs/common';
22
import { TypeOrmModule } from '@nestjs/typeorm';
33
import { Projects } from './project.model';
44
import { ProjectPackages } from './project-packages.model';
5+
import { ProjectsService } from './project.service';
6+
import { ProjectPackagesService } from './project-packages.service';
7+
import { ProjectsResolver } from './project.resolver';
58

69
@Module({
710
imports: [TypeOrmModule.forFeature([Projects, ProjectPackages])],
8-
// providers: [ProjectService],
9-
// exports: [ProjectService],
11+
providers: [ProjectsService, ProjectPackagesService, ProjectsResolver],
12+
exports: [ProjectsService, ProjectPackagesService],
1013
})
1114
export class ProjectModule {}
+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// GraphQL Resolvers for Project APIs
2+
import {
3+
Args,
4+
Field,
5+
Mutation,
6+
ObjectType,
7+
Query,
8+
Resolver,
9+
} from '@nestjs/graphql';
10+
import { ProjectsService } from './project.service';
11+
import { ProjectPackagesService } from './project-packages.service';
12+
import { Projects } from './project.model';
13+
import { ProjectPackages } from './project-packages.model';
14+
import { UpsertProjectInput } from './dto/project.input';
15+
16+
@Resolver(() => Projects)
17+
export class ProjectsResolver {
18+
constructor(
19+
private readonly projectsService: ProjectsService,
20+
private readonly projectPackagesService: ProjectPackagesService
21+
) {}
22+
23+
// -------- All the code need to extract the user id from the token and verify is the project user's or not
24+
// add @GetAuthToken() token: string after test
25+
@Query(() => [Projects])
26+
async getUserProjects(@Args('userId') userId: string): Promise<Projects[]> {
27+
// if (userId != token.id) return 401
28+
29+
return this.projectsService.getProjectsByUser(userId);
30+
}
31+
32+
// @GetAuthToken() token: string
33+
@Query(() => Projects)
34+
async getProjectDetails(@Args('projectId') projectId: string): Promise<Projects> {
35+
return this.projectsService.getProjectById(projectId);
36+
}
37+
38+
// @GetAuthToken() token: string
39+
@Mutation(() => Projects)
40+
async upsertProject(
41+
@Args('upsertProjectInput') upsertProjectInput: UpsertProjectInput
42+
): Promise<Projects> {
43+
return this.projectsService.upsertProject(upsertProjectInput);
44+
}
45+
46+
// @GetAuthToken() token: string
47+
@Mutation(() => Boolean)
48+
async deleteProject(@Args('projectId') projectId: string): Promise<boolean> {
49+
return this.projectsService.deleteProject(projectId);
50+
}
51+
52+
// @GetAuthToken() token: string
53+
@Mutation(() => ProjectPackages)
54+
async addPackageToProject(
55+
@Args('projectId') projectId: string,
56+
@Args('packageContent') packageContent: string
57+
): Promise<ProjectPackages> {
58+
return this.projectPackagesService.addPackageToProject(projectId, packageContent);
59+
}
60+
61+
// @GetAuthToken() token: string
62+
@Mutation(() => Boolean)
63+
async removePackageFromProject(
64+
@Args('projectId') projectId: string,
65+
@Args('packageId') packageId: string
66+
): Promise<boolean> {
67+
return this.projectPackagesService.removePackageFromProject(projectId, packageId);
68+
}
69+
70+
// @GetAuthToken() token: string
71+
@Mutation(() => Boolean)
72+
async updateProjectPath(
73+
@Args('projectId') projectId: string,
74+
@Args('newPath') newPath: string
75+
): Promise<boolean> {
76+
return this.projectsService.updateProjectPath(projectId, newPath);
77+
}
78+
}
+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Project Service for managing Projects
2+
import { Injectable, NotFoundException, InternalServerErrorException } from '@nestjs/common';
3+
import { InjectRepository } from '@nestjs/typeorm';
4+
import { Repository } from 'typeorm';
5+
import { Projects } from './project.model';
6+
import { ProjectPackages } from './project-packages.model';
7+
import { UpsertProjectInput } from './dto/project.input';
8+
9+
@Injectable()
10+
export class ProjectsService {
11+
constructor(
12+
@InjectRepository(Projects)
13+
private projectsRepository: Repository<Projects>,
14+
@InjectRepository(ProjectPackages)
15+
private projectPackagesRepository: Repository<ProjectPackages>
16+
) {}
17+
18+
async getProjectsByUser(userId: string): Promise<Projects[]> {
19+
const project = await this.projectsRepository.find({ where: { user_id: userId }, relations: ['projectPackages'] });
20+
if (!project) {
21+
throw new NotFoundException(`User with ID ${userId} have no project.`);
22+
}
23+
return project;
24+
}
25+
26+
async getProjectById(projectId: string): Promise<Projects> {
27+
const project = await this.projectsRepository.findOne({ where: { id: projectId }, relations: ['projectPackages'] });
28+
if (!project) {
29+
throw new NotFoundException(`Project with ID ${projectId} not found.`);
30+
}
31+
return project;
32+
}
33+
34+
async upsertProject(upsertProjectInput: UpsertProjectInput): Promise<Projects> {
35+
const { project_id, project_name, path, user_id } = upsertProjectInput;
36+
37+
let project;
38+
if (project_id != null) {
39+
project = await this.projectsRepository.findOne({ where: { id: project_id } });
40+
}
41+
42+
43+
if (project) {
44+
// Update existing project
45+
project.project_name = project_name;
46+
project.path = path;
47+
project.user_id = user_id;
48+
49+
// You may also handle the `project_packages` logic here if needed, like updating existing packages.
50+
} else {
51+
// Create a new project if it does not exist
52+
project = this.projectsRepository.create({
53+
project_name,
54+
path,
55+
user_id,
56+
});
57+
}
58+
59+
return await this.projectsRepository.save(project);
60+
}
61+
62+
async deleteProject(projectId: string): Promise<boolean> {
63+
const project = await this.projectsRepository.findOne({ where: { id: projectId } });
64+
if (!project) {
65+
throw new NotFoundException(`Project with ID ${projectId} not found.`);
66+
}
67+
68+
try {
69+
// First, delete related project packages
70+
await this.projectPackagesRepository.delete({ project_id: projectId });
71+
72+
const result = await this.projectsRepository.delete(projectId);
73+
return result.affected > 0;
74+
} catch (error) {
75+
throw new InternalServerErrorException('Error deleting the project.');
76+
}
77+
78+
}
79+
80+
async updateProjectPath(projectId: string, newPath: string): Promise<boolean> {
81+
const project = await this.projectsRepository.findOne({ where: { id: projectId }, relations: ['projectPackages'] });
82+
if (!project) {
83+
throw new NotFoundException(`Project with ID ${projectId} not found.`);
84+
}
85+
86+
const result = await this.projectsRepository.update(projectId, { path: newPath });
87+
return result.affected > 0;
88+
}
89+
}

0 commit comments

Comments
 (0)