/Slack

BackEnd Nest.js

Primary LanguageTypeScript

maxresdefault

Slack

Slack is Clone coding with Slack Service

Purpose

  • Use Node.js build Backend
  • Use Restful API run Server

Environment

JavaScript TypeScript NestJS NodeJS MySQL

Description

  • Use Nest.js build Slack Service Backend.
  • Build Live Chatting Service.
  • Channel Service as Slack.
  • It work Direct Message Service.
  • Channel leader Service

Installation

$ npm install

Running the app

# development
$ npm run start

# watch mode
$ npm run start:dev

# production mode
$ npm run start:prod

Test

# unit tests
$ npm run test

# e2e tests
$ npm run test:e2e

# test coverage
$ npm run test:cov

Slack

Function & Logic

Login & API Service & SignUp

    ConfigModule.forRoot({ isGlobal: true }),
    AuthModule,
    UsersModule,
    WorkspacesModule,
    DmsModule,
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: async (ConfigService: ConfigService) => {
        return {
          type: 'mysql',
          host: 'localhost',
          port: 3306,
          username: ConfigService.get('DB_USERNAME'),
          password: ConfigService.get('DB_PASSWORD'),
          database: ConfigService.get('DB_DATABASE'),
          entities: [
            ChannelChats,
            ChannelMembers,
            Channels,
            DMs,
            Mentions,
            Users,
            WorkspaceMembers,
            Workspaces,
          ],
          synchronize: false, /

          keepConnectionAlive: true,
          logging: true,
          charset: 'utf8mb4',
          autoLoadEntities: true,
          cli: { migrationDir: 'src/migrations' },
          migrations: [__dirname + '/src/migrations/*.ts'],
        };
      },
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_DATABASE,
      autoLoadEntities: true,
      keepConnectionAlive: true,
      migrations: [__dirname + '/migrations/*.ts'],
      charset: 'utf8mb4',
      synchronize: false,
      logging: true,
    }),
    TypeOrmModule.forFeature([Users]),
    EventsModule,
  ],
  controllers: [AppController],
  providers: [AppService],
  exports: [],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer): any {
    consumer.apply(LoggerMiddleware).forRoutes('*');
  }
const config = new DocumentBuilder()
    .setTitle('Slact API')
    .setDescription('API Document for Slact.')
    .setVersion('1.0')
    .addCookieAuth('connect.sid')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);
@UseGuards(NotLoggedInGuard)
  @ApiOperation({ summary: '회원가입' })
  @Post()
  async join(@Body() body: JoinRequestDto) {
    //@Body => express 의 body Pasrer 와 같은것 Dto = Data Transport Object
    await this.usersService.join(body.email, body.nickname, body.password);
  }

Unit Test & E2E Testing

it('should be defined', () => {
    expect(service).toBeDefined();
  });
  /**나중에 할 테스트는 it.todo 으로 하고
   * 바로 해야할 테스트는 it  으로 한다.
   */
  it('findByEmail은 Email을 통해 유저를 찾아야 함', () => {
    expect(service.findByEmail('abc@naver.com')).resolves.toStrictEqual({
      email: 'abc@naver.com',
      id: 1,
    });
  });

  it.todo('findByEmail은 유저를 찾지 못하면 null을 반환해야함!', () => {
    expect(service.findByEmail('abc@naver.com')).resolves.toBe(null);
  });
});
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from './../src/app.module';
import passport from 'passport';
import session from 'express-session';

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    app.use(
      session({
        resave: false,
        saveUninitialized: false,
        secret: process.env.COOKIE_SECRET,
        cookie: {
          httpOnly: true,
        },
      }),
    );
    await app.init();
    app.use(passport.initialize());
    app.use(passport.session());
  });

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Hello World!');
  });
  /** superagent 라이브러리도 있었으나 azios 에 밀려서 supertest 를 다시 만들어서 e2e test 시에 많이 사용된다. */
  /** axios 또한 moxios 가 e2e test 용으로 만들어 져 있다.*/
  it('/users/login (POST)', (done) => {
    return request(app.getHttpServer())
      .post('api/users/login')
      .send({
        email: 'abc@naver.com',
        password: 'nodejsbook1',
      })
      .expect(201, done);
  });
});

Development to do....

  • Use Nest.js to build Slack service from Express.js.
  • Make more Module system.
  • Use less await. Decrease memory usage.
  • QueryBuilder is wonderful DB query.
  • More