├── .gitignore
├── .prettierrc
├── README.md
├── nest-cli.json
├── nodemon-debug.json
├── nodemon.json
├── package-lock.json
├── package.json
├── src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── auth
│ ├── auth.controller.spec.ts
│ ├── auth.controller.ts
│ ├── auth.module.ts
│ ├── auth.service.spec.ts
│ ├── auth.service.ts
│ ├── interfaces
│ │ └── jwt-payload.interface.ts
│ └── strategies
│ │ └── jwt.strategy.ts
├── main.ts
└── users
│ ├── dto
│ ├── create-user.dto.ts
│ └── login-user.dto.ts
│ ├── user.interface.ts
│ ├── user.schema.ts
│ ├── users.controller.spec.ts
│ ├── users.controller.ts
│ ├── users.module.ts
│ ├── users.service.spec.ts
│ └── users.service.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
├── tsconfig.json
├── tsconfig.spec.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Specifies intentionally untracked files to ignore when using Git
2 | # http://git-scm.com/docs/gitignore
3 |
4 | *~
5 | *.sw[mnpcod]
6 | *.log
7 | *.tmp
8 | *.tmp.*
9 | log.txt
10 | *.sublime-project
11 | *.sublime-workspace
12 | .vscode/
13 | npm-debug.log*
14 |
15 | .idea/
16 | .ionic/
17 | .sourcemaps/
18 | .sass-cache/
19 | .tmp/
20 | .versions/
21 | coverage/
22 | www/
23 | node_modules/
24 | tmp/
25 | temp/
26 | platforms/
27 | plugins/
28 | plugins/android.json
29 | plugins/ios.json
30 | $RECYCLE.BIN/
31 |
32 | .DS_Store
33 | Thumbs.db
34 | UserInterfaceState.xcuserstate
35 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
6 | [travis-url]: https://travis-ci.org/nestjs/nest
7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
8 | [linux-url]: https://travis-ci.org/nestjs/nest
9 |
10 | A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 | ## Description
28 |
29 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
30 |
31 | ## Installation
32 |
33 | ```bash
34 | $ npm install
35 | ```
36 |
37 | ## Running the app
38 |
39 | ```bash
40 | # development
41 | $ npm run start
42 |
43 | # watch mode
44 | $ npm run start:dev
45 |
46 | # incremental rebuild (webpack)
47 | $ npm run webpack
48 | $ npm run start:hmr
49 |
50 | # production mode
51 | $ npm run start:prod
52 | ```
53 |
54 | ## Test
55 |
56 | ```bash
57 | # unit tests
58 | $ npm run test
59 |
60 | # e2e tests
61 | $ npm run test:e2e
62 |
63 | # test coverage
64 | $ npm run test:cov
65 | ```
66 |
67 | ## Support
68 |
69 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
70 |
71 | ## Stay in touch
72 |
73 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
74 | - Website - [https://nestjs.com](https://nestjs.com/)
75 | - Twitter - [@nestframework](https://twitter.com/nestframework)
76 |
77 | ## License
78 |
79 | Nest is [MIT licensed](LICENSE).
80 |
--------------------------------------------------------------------------------
/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "language": "ts",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src"
5 | }
6 |
--------------------------------------------------------------------------------
/nodemon-debug.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["src"],
3 | "ext": "ts",
4 | "ignore": ["src/**/*.spec.ts"],
5 | "exec": "node --inspect-brk -r ts-node/register -r tsconfig-paths/register src/main.ts"
6 | }
7 |
--------------------------------------------------------------------------------
/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["src"],
3 | "ext": "ts",
4 | "ignore": ["src/**/*.spec.ts"],
5 | "exec": "ts-node -r tsconfig-paths/register src/main.ts"
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nest-jwt-auth",
3 | "version": "0.0.0",
4 | "description": "description",
5 | "author": "",
6 | "license": "MIT",
7 | "scripts": {
8 | "build": "tsc -p tsconfig.build.json",
9 | "format": "prettier --write \"src/**/*.ts\"",
10 | "start": "ts-node -r tsconfig-paths/register src/main.ts",
11 | "start:dev": "nodemon",
12 | "start:debug": "nodemon --config nodemon-debug.json",
13 | "prestart:prod": "rimraf dist && tsc",
14 | "start:prod": "node dist/main.js",
15 | "lint": "tslint -p tsconfig.json -c tslint.json",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --config ./test/jest-e2e.json"
21 | },
22 | "dependencies": {
23 | "@nestjs/common": "^5.4.0",
24 | "@nestjs/core": "^5.4.0",
25 | "@nestjs/jwt": "^0.2.0",
26 | "@nestjs/mongoose": "^5.2.2",
27 | "@nestjs/passport": "^5.1.0",
28 | "bcrypt": "^3.0.2",
29 | "mongoose": "^5.3.15",
30 | "passport": "^0.4.0",
31 | "passport-jwt": "^4.0.0",
32 | "reflect-metadata": "^0.1.12",
33 | "rimraf": "^2.6.2",
34 | "rxjs": "^6.2.2",
35 | "typescript": "^3.0.1"
36 | },
37 | "devDependencies": {
38 | "@nestjs/testing": "^5.1.0",
39 | "@types/express": "^4.16.0",
40 | "@types/jest": "^23.3.1",
41 | "@types/node": "^10.7.1",
42 | "@types/supertest": "^2.0.5",
43 | "jest": "^23.5.0",
44 | "nodemon": "^1.18.3",
45 | "prettier": "^1.14.2",
46 | "supertest": "^3.1.0",
47 | "ts-jest": "^23.1.3",
48 | "ts-loader": "^4.4.2",
49 | "ts-node": "^7.0.1",
50 | "tsconfig-paths": "^3.5.0",
51 | "tslint": "5.11.0"
52 | },
53 | "jest": {
54 | "moduleFileExtensions": [
55 | "js",
56 | "json",
57 | "ts"
58 | ],
59 | "rootDir": "src",
60 | "testRegex": ".spec.ts$",
61 | "transform": {
62 | "^.+\\.(t|j)s$": "ts-jest"
63 | },
64 | "coverageDirectory": "../coverage",
65 | "testEnvironment": "node"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let app: TestingModule;
7 |
8 | beforeAll(async () => {
9 | app = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 | });
14 |
15 | describe('root', () => {
16 | it('should return "Hello World!"', () => {
17 | const appController = app.get(AppController);
18 | expect(appController.getHello()).toBe('Hello World!');
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { MongooseModule } from '@nestjs/mongoose';
3 | import { AppController } from './app.controller';
4 | import { AppService } from './app.service';
5 | import { AuthModule } from './auth/auth.module';
6 | import { UsersModule } from './users/users.module';
7 |
8 | @Module({
9 | imports: [
10 | AuthModule,
11 | UsersModule,
12 | MongooseModule.forRoot('mongodb://localhost/authexample')
13 | ],
14 | controllers: [AppController],
15 | providers: [AppService],
16 | })
17 | export class AppModule {}
18 |
--------------------------------------------------------------------------------
/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/auth/auth.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AuthController } from './auth.controller';
3 |
4 | describe('Auth Controller', () => {
5 | let module: TestingModule;
6 |
7 | beforeAll(async () => {
8 | module = await Test.createTestingModule({
9 | controllers: [AuthController],
10 | }).compile();
11 | });
12 | it('should be defined', () => {
13 | const controller: AuthController = module.get(AuthController);
14 | expect(controller).toBeDefined();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/auth/auth.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Post, Body } from '@nestjs/common';
2 | import { AuthService } from './auth.service';
3 | import { LoginUserDto } from '../users/dto/login-user.dto'
4 |
5 | @Controller('auth')
6 | export class AuthController {
7 |
8 | constructor(private authService: AuthService) {
9 |
10 | }
11 |
12 | @Post()
13 | async login(@Body() loginUserDto: LoginUserDto){
14 | return await this.authService.validateUserByPassword(loginUserDto);
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/src/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { JwtModule } from '@nestjs/jwt';
3 | import { AuthService } from './auth.service';
4 | import { AuthController } from './auth.controller';
5 | import { JwtStrategy } from './strategies/jwt.strategy';
6 | import { UsersModule } from '../users/users.module';
7 | import { PassportModule } from '@nestjs/passport';
8 |
9 | @Module({
10 | imports: [
11 | PassportModule.register({ defaultStrategy: 'jwt', session: false }),
12 | JwtModule.register({
13 | secretOrPrivateKey: 'thisismykickasssecretthatiwilltotallychangelater',
14 | signOptions: {
15 | expiresIn: 3600
16 | }
17 | }),
18 | UsersModule
19 | ],
20 | controllers: [AuthController],
21 | providers: [AuthService, JwtStrategy]
22 | })
23 | export class AuthModule {}
--------------------------------------------------------------------------------
/src/auth/auth.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AuthService } from './auth.service';
3 |
4 | describe('AuthService', () => {
5 | let service: AuthService;
6 |
7 | beforeAll(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [AuthService],
10 | }).compile();
11 | service = module.get(AuthService);
12 | });
13 | it('should be defined', () => {
14 | expect(service).toBeDefined();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, UnauthorizedException } from '@nestjs/common';
2 | import { JwtService } from '@nestjs/jwt';
3 | import { LoginUserDto } from '../users/dto/login-user.dto';
4 | import { UsersService } from '../users/users.service';
5 | import { JwtPayload } from './interfaces/jwt-payload.interface';
6 |
7 | @Injectable()
8 | export class AuthService {
9 |
10 | constructor(private usersService: UsersService, private jwtService: JwtService){
11 |
12 | }
13 |
14 | async validateUserByPassword(loginAttempt: LoginUserDto) {
15 |
16 | // This will be used for the initial login
17 | let userToAttempt = await this.usersService.findOneByEmail(loginAttempt.email);
18 |
19 | return new Promise((resolve) => {
20 |
21 | // Check the supplied password against the hash stored for this email address
22 | userToAttempt.checkPassword(loginAttempt.password, (err, isMatch) => {
23 |
24 | if(err) throw new UnauthorizedException();
25 |
26 | if(isMatch){
27 | // If there is a successful match, generate a JWT for the user
28 | resolve(this.createJwtPayload(userToAttempt));
29 |
30 | } else {
31 | throw new UnauthorizedException();
32 | }
33 |
34 | });
35 |
36 | });
37 |
38 | }
39 |
40 | async validateUserByJwt(payload: JwtPayload) {
41 |
42 | // This will be used when the user has already logged in and has a JWT
43 | let user = await this.usersService.findOneByEmail(payload.email);
44 |
45 | if(user){
46 | return this.createJwtPayload(user);
47 | } else {
48 | throw new UnauthorizedException();
49 | }
50 |
51 | }
52 |
53 | createJwtPayload(user){
54 |
55 | let data: JwtPayload = {
56 | email: user.email
57 | };
58 |
59 | let jwt = this.jwtService.sign(data);
60 |
61 | return {
62 | expiresIn: 3600,
63 | token: jwt
64 | }
65 |
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/auth/interfaces/jwt-payload.interface.ts:
--------------------------------------------------------------------------------
1 | export interface JwtPayload {
2 | email: string;
3 | }
--------------------------------------------------------------------------------
/src/auth/strategies/jwt.strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, UnauthorizedException } from '@nestjs/common';
2 | import { ExtractJwt, Strategy } from 'passport-jwt';
3 | import { AuthService } from '../auth.service';
4 | import { PassportStrategy } from '@nestjs/passport';
5 | import { JwtPayload } from '../interfaces/jwt-payload.interface';
6 |
7 | @Injectable()
8 | export class JwtStrategy extends PassportStrategy(Strategy) {
9 |
10 | constructor(private authService: AuthService){
11 |
12 | super({
13 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
14 | secretOrKey: 'thisismykickasssecretthatiwilltotallychangelater'
15 | });
16 |
17 | }
18 |
19 | async validate(payload: JwtPayload){
20 |
21 | const user = await this.authService.validateUserByJwt(payload);
22 |
23 | if(!user){
24 | throw new UnauthorizedException();
25 | }
26 |
27 | return user;
28 |
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | app.enableCors();
7 | await app.listen(3000);
8 | }
9 | bootstrap();
10 |
--------------------------------------------------------------------------------
/src/users/dto/create-user.dto.ts:
--------------------------------------------------------------------------------
1 | export class CreateUserDto {
2 | readonly email: string;
3 | readonly password: string;
4 | }
--------------------------------------------------------------------------------
/src/users/dto/login-user.dto.ts:
--------------------------------------------------------------------------------
1 | export class LoginUserDto {
2 | readonly email: string;
3 | readonly password: string;
4 | }
--------------------------------------------------------------------------------
/src/users/user.interface.ts:
--------------------------------------------------------------------------------
1 | export interface User {
2 | email: string
3 | }
--------------------------------------------------------------------------------
/src/users/user.schema.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from 'mongoose';
2 | import * as bcrypt from 'bcrypt';
3 |
4 | export const UserSchema = new mongoose.Schema({
5 | email: {
6 | type: String,
7 | unique: true,
8 | required: true
9 | },
10 | password: {
11 | type: String,
12 | required: true
13 | }
14 | });
15 |
16 | // NOTE: Arrow functions are not used here as we do not want to use lexical scope for 'this'
17 | UserSchema.pre('save', function(next){
18 |
19 | let user = this;
20 |
21 | // Make sure not to rehash the password if it is already hashed
22 | if(!user.isModified('password')) return next();
23 |
24 | // Generate a salt and use it to hash the user's password
25 | bcrypt.genSalt(10, (err, salt) => {
26 |
27 | if(err) return next(err);
28 |
29 | bcrypt.hash(user.password, salt, (err, hash) => {
30 |
31 | if(err) return next(err);
32 | user.password = hash;
33 | next();
34 |
35 | });
36 |
37 | });
38 |
39 | });
40 |
41 | UserSchema.methods.checkPassword = function(attempt, callback){
42 |
43 | let user = this;
44 |
45 | bcrypt.compare(attempt, user.password, (err, isMatch) => {
46 | if(err) return callback(err);
47 | callback(null, isMatch);
48 | });
49 |
50 | };
--------------------------------------------------------------------------------
/src/users/users.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { UsersController } from './users.controller';
3 |
4 | describe('Users Controller', () => {
5 | let module: TestingModule;
6 |
7 | beforeAll(async () => {
8 | module = await Test.createTestingModule({
9 | controllers: [UsersController],
10 | }).compile();
11 | });
12 | it('should be defined', () => {
13 | const controller: UsersController = module.get(UsersController);
14 | expect(controller).toBeDefined();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/users/users.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
2 | import { CreateUserDto } from './dto/create-user.dto';
3 | import { UsersService } from './users.service';
4 | import { AuthGuard } from '@nestjs/passport';
5 |
6 | @Controller('users')
7 | export class UsersController {
8 |
9 | constructor(private usersService: UsersService) {
10 |
11 | }
12 |
13 | @Post()
14 | async create(@Body() createUserDto: CreateUserDto) {
15 | return await this.usersService.create(createUserDto);
16 | }
17 |
18 | // This route will require successfully passing our default auth strategy (JWT) in order
19 | // to access the route
20 | @Get('test')
21 | @UseGuards(AuthGuard())
22 | testAuthRoute(){
23 | return {
24 | message: 'You did it!'
25 | }
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/src/users/users.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { MongooseModule } from '@nestjs/mongoose';
3 | import { PassportModule } from '@nestjs/passport';
4 | import { UsersController } from './users.controller';
5 | import { UsersService } from './users.service';
6 | import { UserSchema } from './user.schema';
7 |
8 | @Module({
9 | imports: [
10 | MongooseModule.forFeature([{name: 'User', schema: UserSchema}]),
11 | PassportModule.register({ defaultStrategy: 'jwt', session: false })
12 | ],
13 | exports: [UsersService],
14 | controllers: [UsersController],
15 | providers: [UsersService]
16 | })
17 | export class UsersModule {}
18 |
--------------------------------------------------------------------------------
/src/users/users.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { UsersService } from './users.service';
3 |
4 | describe('UsersService', () => {
5 | let service: UsersService;
6 |
7 | beforeAll(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [UsersService],
10 | }).compile();
11 | service = module.get(UsersService);
12 | });
13 | it('should be defined', () => {
14 | expect(service).toBeDefined();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/users/users.service.ts:
--------------------------------------------------------------------------------
1 | import { Model } from 'mongoose';
2 | import { Injectable } from '@nestjs/common';
3 | import { InjectModel } from '@nestjs/mongoose';
4 | import { User } from './user.interface';
5 | import { CreateUserDto } from './dto/create-user.dto';
6 |
7 | @Injectable()
8 | export class UsersService {
9 |
10 | constructor(@InjectModel('User') private userModel: Model) {}
11 |
12 | async create(createUserDto: CreateUserDto) {
13 |
14 | let createdUser = new this.userModel(createUserDto);
15 | return await createdUser.save();
16 |
17 | }
18 |
19 | async findOneByEmail(email): Model {
20 |
21 | return await this.userModel.findOne({email: email});
22 |
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { INestApplication } from '@nestjs/common';
2 | import { Test } from '@nestjs/testing';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeAll(async () => {
10 | const moduleFixture = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src/**/*"],
4 | "exclude": ["node_modules", "**/*.spec.ts"]
5 | }
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "noImplicitAny": false,
6 | "removeComments": true,
7 | "noLib": false,
8 | "allowSyntheticDefaultImports": true,
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "target": "es6",
12 | "sourceMap": true,
13 | "outDir": "./dist",
14 | "baseUrl": "./"
15 | },
16 | "exclude": ["node_modules"]
17 | }
18 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "types": ["jest", "node"]
5 | },
6 | "include": ["**/*.spec.ts", "**/*.d.ts"]
7 | }
8 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint:recommended"],
4 | "jsRules": {
5 | "no-unused-expression": true
6 | },
7 | "rules": {
8 | "quotemark": [true, "single"],
9 | "member-access": [false],
10 | "ordered-imports": [false],
11 | "max-line-length": [true, 150],
12 | "member-ordering": [false],
13 | "interface-name": [false],
14 | "arrow-parens": false,
15 | "object-literal-sort-keys": false
16 | },
17 | "rulesDirectory": []
18 | }
19 |
--------------------------------------------------------------------------------