author: Aurelien Loyer / Emmanuel Demey summary: Pendant ce codelab, nous allons créer un backend pour une application d'e-commerce avec le framework NestJS. id: docs/lab ga: UA-137363732-2 feedback link: https://twitter.com/AurelienLoyer

Pour faire ce codelab, vous avez besoin des outils suivants :

npm install -g @nestjs/cli
# OU
yarn global add @nestjs/cli
git clone -b step0 https://github.com/T3kstiil3/codelab-nestjs-corrections
cd codelab-nestjs-corrections
npm install # yarn

Si vous utilisez VSCode, nous vous proposons une selection d'extensions que vous pouvez utiliser pour un projet NestJS. Pour les lister, dans la page dédiée aux extensions, faites une recherche via le mot clé @recommanded. Normalement VSCode listera notre liste d'extensions.

Si vous exécutez la commande suivante, votre API sera disponible à l'URL http://localhost:3000

 npm run start

Nous améliorerons cette intégration au fur et à mesure des TPs.

Voici de plus quelques liens qui pourraient vous être utiles tout au long de ce codelab :

git checkout step1 -f

Un produit sera représenté par la classe TypeScript suivante :

import { ApiProperty, ApiPropertyOptions } from '@nestjs/swagger';

export class Product {
  @ApiProperty({ example: 12 } as ApiPropertyOptions)
  readonly id: number;

  @ApiProperty({ example: 'Super product' } as ApiPropertyOptions)
  readonly label?: string;

  @ApiProperty({
    example:
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ...',
  } as ApiPropertyOptions)
  readonly description?: string;

  @ApiProperty({ example: '' } as ApiPropertyOptions)
  readonly image?: string;

  @ApiProperty({ example: 15.0 } as ApiPropertyOptions)
  readonly price?: number;

  @ApiProperty({ example: 5 } as ApiPropertyOptions)
  readonly stock?: number;
}

Un fichier products.json est à votre disposition. Il contient un jeu de données que vous pouvez utiliser pour cette API.

Voici de plus quelques liens qui pourraient vous être utiles tout au long de ce codelab :

git checkout step2 -f

Nous allons à présent créer un module NestJS afin d'y ajouter la fonctionnalité de gestion des produits.

git checkout step2 -f
nest generate module products
nest generate controller products

Voici de plus quelques liens qui pourraient vous êtres utiles tout au long de ce codelab :

git checkout step3 -f

Nous allons à présent externaliser le code métier dans un service dédié que nous nommerons ProductsService.

nest generate service products

Voici de plus quelques liens qui pourraient vous êtres utiles tout au long de ce codelab :

git checkout step4 -f

Pour cela, nous allons utiliser des décorateurs définis dans le module class-validator.

Voici de plus quelques liens qui pourraient vous êtres utiles tout au long de ce codelab :

git checkout step5 -f

Afin de faciliter l'écriture des tests, nous allons tout d'abord externaliser notre tableau de produits dans un nouveau provider

@Module({
  controllers: [ProductsController],
  providers: [
    ProductsService,
    { provide: 'ProductsJson', useValue: productsJson },
  ],
})
@Injectable()
export class ProductsService {
  private products: Product[];

  constructor(
    @Inject('ProductsJson') private readonly productsJson: Product[],
  ) {
    this.products = productsJson;
  }
}
git checkout step6 -f
npm install @nestjs/jwt @nestjs/passport @nestjs/platform-express passport passport-jwt
  nest generate module users 
[
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.register({
      secretOrPrivateKey: 'secretKey',
      signOptions: {
        expiresIn: 3600,
      },
    }),
]

Nous allons à présent créer deux service :

nest generate service users/JwtStrategy
nest generate service users/users
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly usersService: UsersService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'secretKey',
    });
  }

  async validate(payload: JwtPayload) {
    const user = await this.usersService.validateUser(payload);
    if (!user) {
      throw new UnauthorizedException('The user is unauthorized');
    }
    return user;
  }
}
    [
        {
            "id": 1,
            "username": "Aurel",
            "email": "aurelien@loyer.fr",
            "password": "password",
            "cart": {}
        },
        {
            "id": 2,
            "username": "Manu",
            "email": "emmanuel@demey.fr",
            "password": "password",
            "cart": {}
        }
    ]
* une méthode `login` qui prendra en paramètre l'email et le password d'un utilisateur. Après avoir vérifié que la combinaison email/password correspond bien à un utilisateur, cette méthode retournera le token JWT nécessaire pour s'authentifier. Pour cela, on utilisera le service `JwtService` du module `@nestjs/jwt`
const accessToken = this.jwtService.sign(payload);
return {
    expiresIn: 3600,
    accessToken: `Bearer ${accessToken}`,
};

Voici de plus quelques liens qui pourraient vous êtres utiles tout au long de ce codelab :