Skip to content

Commit 51a3b99

Browse files
authored
Merge branch 'develop' into bug-fe-#343
2 parents e5a3cb2 + 8b8a3dd commit 51a3b99

17 files changed

+167
-140
lines changed

apps/backend/src/app.module.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ import { AuthModule } from './auth/auth.module';
2020
import { UserModule } from './user/user.module';
2121
import { WorkspaceModule } from './workspace/workspace.module';
2222
import { RoleModule } from './role/role.module';
23+
import { TasksModule } from './tasks/tasks.module';
24+
import { ScheduleModule } from '@nestjs/schedule';
2325

2426
@Module({
2527
imports: [
28+
ScheduleModule.forRoot(),
2629
ServeStaticModule.forRoot({
2730
rootPath: path.join(__dirname, '..', '..', 'frontend', 'dist'),
2831
}),
@@ -34,7 +37,14 @@ import { RoleModule } from './role/role.module';
3437
imports: [ConfigModule],
3538
inject: [ConfigService],
3639
useFactory: (configService: ConfigService) => ({
37-
type: 'sqlite',
40+
41+
// type: 'sqlite',
42+
// database: 'db.sqlite',
43+
type: 'postgres',
44+
host: configService.get('DB_HOST'),
45+
port: configService.get('DB_PORT'),
46+
username: configService.get('DB_USER'),
47+
password: configService.get('DB_PASSWORD'),
3848
database: configService.get('DB_NAME'),
3949
entities: [Node, Page, Edge, User, Workspace, Role],
4050
logging: true,
@@ -50,6 +60,7 @@ import { RoleModule } from './role/role.module';
5060
UserModule,
5161
WorkspaceModule,
5262
RoleModule,
63+
TasksModule,
5364
],
5465
controllers: [AppController],
5566
providers: [AppService],

apps/backend/src/auth/auth.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Module } from '@nestjs/common';
22
import { UserRepository } from '../user/user.repository';
3-
import { UserModule } from 'src/user/user.module';
3+
import { UserModule } from '../user/user.module';
44
import { AuthService } from './auth.service';
55
import { AuthController } from './auth.controller';
66
import { NaverStrategy } from './strategies/naver.strategy';

apps/backend/src/auth/auth.service.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { SignUpDto } from './dtos/signUp.dto';
55
import { User } from '../user/user.entity';
66
import { UpdateUserDto } from './dtos/UpdateUser.dto';
77
import { UserNotFoundException } from '../exception/user.exception';
8+
import { Snowflake } from '@theinternetfolks/snowflake';
89

910
describe('AuthService', () => {
1011
let authService: AuthService;
@@ -68,9 +69,8 @@ describe('AuthService', () => {
6869
provider: 'naver',
6970
7071
};
71-
const generated
72-
73-
flakeId = Snowflake.generate(); // Snowflake.generate()의 mock 값을 준비
72+
73+
const generatedSnowflakeId = Snowflake.generate(); // Snowflake.generate()의 mock 값을 준비
7474
const newDate = new Date();
7575
const createdUser = {
7676
providerId: dto.providerId,

apps/backend/src/auth/auth.service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { UpdateUserDto } from './dtos/UpdateUser.dto';
66
import { UserNotFoundException } from '../exception/user.exception';
77
import { Snowflake } from '@theinternetfolks/snowflake';
88

9-
109
@Injectable()
1110
export class AuthService {
1211
constructor(private readonly userRepository: UserRepository) {}

apps/backend/src/node/node.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import { CreateNodeDto } from './dtos/createNode.dto';
99
import { UpdateNodeDto } from './dtos/updateNode.dto';
1010
import { MoveNodeDto } from './dtos/moveNode.dto';
1111
import { WorkspaceRepository } from '../workspace/workspace.repository';
12+
import { Workspace } from '../workspace/workspace.entity';
1213

1314
describe('NodeService', () => {
1415
let service: NodeService;
1516
let nodeRepository: jest.Mocked<NodeRepository>;
1617
let pageRepository: jest.Mocked<PageRepository>;
1718
let workspaceRepository: jest.Mocked<WorkspaceRepository>;
1819

19-
2020
beforeEach(async () => {
2121
const module: TestingModule = await Test.createTestingModule({
2222
providers: [
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { IsString, IsJSON, IsOptional, IsNumber } from 'class-validator';
2+
import { ApiProperty } from '@nestjs/swagger';
3+
4+
export class UpdatePartialPageDto {
5+
@ApiProperty({
6+
example: 1,
7+
description: 'page PK',
8+
})
9+
@IsNumber()
10+
id: number;
11+
12+
@ApiProperty({
13+
example: '페이지 제목입니다.',
14+
description: '페이지 제목.',
15+
})
16+
@IsString()
17+
@IsOptional()
18+
title?: string;
19+
20+
@ApiProperty({
21+
example: "{'doc' : 'type'}",
22+
description: '페이지 내용 JSON 형태',
23+
})
24+
@IsJSON()
25+
@IsOptional()
26+
content?: JSON;
27+
28+
@ApiProperty({
29+
example: '📝',
30+
description: '페이지 이모지',
31+
required: false,
32+
})
33+
@IsString()
34+
@IsOptional()
35+
emoji?: string;
36+
}

apps/backend/src/page/page.entity.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
CreateDateColumn,
99
UpdateDateColumn,
1010
VersionColumn,
11-
IsNull,
1211
} from 'typeorm';
1312
import { Node } from '../node/node.entity';
1413
import { Workspace } from '../workspace/workspace.entity';

apps/backend/src/page/page.repository.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { Injectable } from '@nestjs/common';
1+
import { Injectable, Logger } from '@nestjs/common';
22
import { DataSource, Repository } from 'typeorm';
33
import { Page } from './page.entity';
44
import { InjectDataSource } from '@nestjs/typeorm';
5+
import { UpdatePartialPageDto } from './dtos/updatePartialPage.dto';
56

67
@Injectable()
78
export class PageRepository extends Repository<Page> {
@@ -20,12 +21,7 @@ export class PageRepository extends Repository<Page> {
2021
});
2122
}
2223

23-
async bulkUpdate(pages) {
24-
await this.createQueryBuilder()
25-
.insert()
26-
.into(Page)
27-
.values(pages)
28-
.orUpdate(['title', 'content'], ['id'])
29-
.execute();
24+
async bulkUpdate(pages: UpdatePartialPageDto[]) {
25+
await Promise.all(pages.map((page) => this.update(page.id, page)));
3026
}
3127
}

apps/backend/src/page/page.service.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('PageService', () => {
2828
save: jest.fn(),
2929
delete: jest.fn(),
3030
findOneBy: jest.fn(),
31+
findOne: jest.fn(),
3132
findPagesByWorkspace: jest.fn(),
3233
},
3334
},
@@ -135,6 +136,7 @@ describe('PageService', () => {
135136
content: {} as JSON,
136137
emoji: undefined,
137138
workspace: workspace1,
139+
node: newNode,
138140
});
139141
});
140142
});
@@ -235,19 +237,22 @@ describe('PageService', () => {
235237
emoji: null,
236238
workspace: null,
237239
};
238-
jest.spyOn(pageRepository, 'findOneBy').mockResolvedValue(expectedPage);
240+
jest.spyOn(pageRepository, 'findOne').mockResolvedValue(expectedPage);
239241

240242
await expect(service.findPageById(1)).resolves.toEqual(expectedPage);
241243
});
242244

243245
it('id에 해당하는 페이지가 없을 경우 PageNotFoundException을 throw한다.', async () => {
244-
jest.spyOn(pageRepository, 'findOneBy').mockResolvedValue(undefined);
246+
jest.spyOn(pageRepository, 'findOne').mockResolvedValue(undefined);
245247

246248
await expect(service.findPageById(1)).rejects.toThrow(
247249
PageNotFoundException,
248250
);
249251

250-
expect(pageRepository.findOneBy).toHaveBeenCalledWith({ id: 1 });
252+
expect(pageRepository.findOne).toHaveBeenCalledWith({
253+
where: { id: 1 },
254+
relations: ['node'],
255+
});
251256
});
252257
});
253258

apps/backend/src/page/page.service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { PageRepository } from './page.repository';
55
import { Page } from './page.entity';
66
import { CreatePageDto } from './dtos/createPage.dto';
77
import { UpdatePageDto } from './dtos/updatePage.dto';
8+
import { UpdatePartialPageDto } from './dtos/updatePartialPage.dto';
89
import { PageNotFoundException } from '../exception/page.exception';
910
import { WorkspaceNotFoundException } from '../exception/workspace.exception';
1011

@@ -37,6 +38,7 @@ export class PageService {
3738
content,
3839
emoji,
3940
workspace,
41+
node,
4042
});
4143

4244
// 페이지와 노드를 서로 연결하여 저장한다.
@@ -81,13 +83,16 @@ export class PageService {
8183
return await this.pageRepository.save(newPage);
8284
}
8385

84-
async updateBulkPage(pages: UpdatePageDto[]) {
86+
async updateBulkPage(pages: UpdatePartialPageDto[]) {
8587
await this.pageRepository.bulkUpdate(pages);
8688
}
8789

8890
async findPageById(id: number): Promise<Page> {
8991
// 페이지를 조회한다.
90-
const page = await this.pageRepository.findOneBy({ id });
92+
const page = await this.pageRepository.findOne({
93+
where: { id },
94+
relations: ['node'],
95+
});
9196

9297
// 페이지가 없으면 NotFound 에러
9398
if (!page) {

0 commit comments

Comments
 (0)