Compare commits

...

7 Commits

Author SHA1 Message Date
taolin
18dff6d508 c 2022-07-23 00:52:24 +08:00
4bfd893199 - 2022-06-01 16:27:05 +08:00
a86d012adc controller 2022-06-01 15:40:31 +08:00
陶林
0c5257d06d readme 2022-04-08 16:28:07 +08:00
陶林
ff24516a7f demo 2022-04-08 16:27:03 +08:00
陶林
2f587c8f1d init 2022-04-08 13:16:51 +08:00
陶林
14e6d6ffee init 2022-04-08 12:47:32 +08:00
32 changed files with 4221 additions and 3962 deletions

0
.eslintrc.js Normal file → Executable file
View File

0
.gitignore vendored Normal file → Executable file
View File

0
.prettierrc Normal file → Executable file
View File

44
README.md Normal file → Executable file
View File

@@ -24,50 +24,18 @@
## Description
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
## Installation
```bash
$ npm install
```shell
npm i -g @nestjs/cli
```
## Running the app
```bash
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prod
```shell
npm run start:dev
```
## Test
http://127.0.0.1:3000/api/#/
```bash
# unit tests
$ npm run test
# e2e tests
$ npm run test:e2e
# test coverage
$ npm run test:cov
```
## Support
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).
## Stay in touch
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).
![](https://alicdn.taoya.art/note/20220408162739.png)

0
nest-cli.json Normal file → Executable file
View File

88
package-lock.json generated Normal file → Executable file
View File

@@ -17,6 +17,8 @@
"@nestjs/typeorm": "^8.0.3",
"hbs": "^4.2.0",
"mysql2": "^2.3.3",
"nestjs-rate-limiter": "^3.1.0",
"nestjs-real-ip": "^2.1.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
@@ -1718,6 +1720,11 @@
"resolved": "https://registry.npmmirror.com/@sqltools/formatter/-/formatter-1.2.3.tgz",
"integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg=="
},
"node_modules/@supercharge/request-ip": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz",
"integrity": "sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ=="
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz",
@@ -5304,6 +5311,12 @@
"node": ">= 0.10"
}
},
"node_modules/is_js": {
"version": "0.9.0",
"resolved": "https://registry.npmmirror.com/is_js/-/is_js-0.9.0.tgz",
"integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==",
"peer": true
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -6927,6 +6940,26 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"license": "MIT"
},
"node_modules/nestjs-rate-limiter": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/nestjs-rate-limiter/-/nestjs-rate-limiter-3.1.0.tgz",
"integrity": "sha512-Qwr6daFvNppy038rs0iCQzX/uC3/czCC/2jATcETLIvyFmcBgySOMg7HGEquPKUZDX9lbc06Tn9L6U3QZS13HQ==",
"dependencies": {
"rate-limiter-flexible": "2.1.10"
}
},
"node_modules/nestjs-real-ip": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/nestjs-real-ip/-/nestjs-real-ip-2.1.0.tgz",
"integrity": "sha512-nq3q1PtrvQ1UffDfE8AWUFTXm70wahTk+v708bdDJTSySi3YUTZ5T0wmFoDDOiiKSc5Phx8n8VW3EaFbtqRpIw==",
"dependencies": {
"@supercharge/request-ip": "^1.2.0"
},
"peerDependencies": {
"@nestjs/common": "^8.0.0",
"request-ip": "^2.1.3"
}
},
"node_modules/node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmmirror.com/node-emoji/-/node-emoji-1.11.0.tgz",
@@ -7572,6 +7605,11 @@
"node": ">= 0.6"
}
},
"node_modules/rate-limiter-flexible": {
"version": "2.1.10",
"resolved": "https://registry.npmmirror.com/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz",
"integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw=="
},
"node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz",
@@ -7684,6 +7722,15 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/request-ip": {
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/request-ip/-/request-ip-2.1.3.tgz",
"integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==",
"peer": true,
"dependencies": {
"is_js": "^0.9.0"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
@@ -10770,6 +10817,11 @@
"resolved": "https://registry.npmmirror.com/@sqltools/formatter/-/formatter-1.2.3.tgz",
"integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg=="
},
"@supercharge/request-ip": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz",
"integrity": "sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ=="
},
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz",
@@ -13343,6 +13395,12 @@
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"is_js": {
"version": "0.9.0",
"resolved": "https://registry.npmmirror.com/is_js/-/is_js-0.9.0.tgz",
"integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==",
"peer": true
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -14557,6 +14615,22 @@
"resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
"nestjs-rate-limiter": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/nestjs-rate-limiter/-/nestjs-rate-limiter-3.1.0.tgz",
"integrity": "sha512-Qwr6daFvNppy038rs0iCQzX/uC3/czCC/2jATcETLIvyFmcBgySOMg7HGEquPKUZDX9lbc06Tn9L6U3QZS13HQ==",
"requires": {
"rate-limiter-flexible": "2.1.10"
}
},
"nestjs-real-ip": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/nestjs-real-ip/-/nestjs-real-ip-2.1.0.tgz",
"integrity": "sha512-nq3q1PtrvQ1UffDfE8AWUFTXm70wahTk+v708bdDJTSySi3YUTZ5T0wmFoDDOiiKSc5Phx8n8VW3EaFbtqRpIw==",
"requires": {
"@supercharge/request-ip": "^1.2.0"
}
},
"node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmmirror.com/node-emoji/-/node-emoji-1.11.0.tgz",
@@ -14987,6 +15061,11 @@
"resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"rate-limiter-flexible": {
"version": "2.1.10",
"resolved": "https://registry.npmmirror.com/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz",
"integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw=="
},
"raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz",
@@ -15068,6 +15147,15 @@
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
"dev": true
},
"request-ip": {
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/request-ip/-/request-ip-2.1.3.tgz",
"integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==",
"peer": true,
"requires": {
"is_js": "^0.9.0"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",

2
package.json Normal file → Executable file
View File

@@ -29,6 +29,8 @@
"@nestjs/typeorm": "^8.0.3",
"hbs": "^4.2.0",
"mysql2": "^2.3.3",
"nestjs-rate-limiter": "^3.1.0",
"nestjs-real-ip": "^2.1.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",

0
public/a.txt Normal file → Executable file
View File

17
src/aaa/aaa.controller.spec.ts Executable file
View File

@@ -0,0 +1,17 @@
import { Test, TestingModule } from '@nestjs/testing';
describe('AaaController', () => {
let controller: AaaController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AaaController],
}).compile();
controller = module.get<AaaController>(AaaController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

16
src/app.controller.ts Normal file → Executable file
View File

@@ -14,8 +14,10 @@ import {
import { AppService } from './app.service';
import { Request } from 'express';
import { ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
import { RealIP } from 'nestjs-real-ip';
@Controller()
@ApiTags('基本使用')
export class AppController {
// constructor(private readonly appService: AppService) {}
@@ -24,6 +26,20 @@ export class AppController {
// return this.appService.getHello();
// }
// 基础路由
@Get('/getip')
@ApiTags('获取访问者IP')
getIP(@RealIP() ip: string): string {
// npm i nestjs-real-ip
return ip;
}
@Get()
@Redirect('/api', 302)
hello() {
return '';
}
@Get('/r1')
@HttpCode(200)
getR1(): string {

15
src/app.module.ts Normal file → Executable file
View File

@@ -3,9 +3,19 @@ import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ScheduleModule } from '@nestjs/schedule';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RateLimiterModule } from 'nestjs-rate-limiter';
import User from './entity/user';
import { TechModule } from './apps/pluginORM';
import { CatsModule } from './apps/pluginORM/cats/cats.module';
import { RateModule } from './apps/pluginRate';
import { UseControllerModule } from './apps/useController';
@Module({
imports: [
TechModule,
RateModule,
RateLimiterModule,
UseControllerModule,
ScheduleModule.forRoot(),
TypeOrmModule.forRoot({
type: 'mysql',
@@ -15,8 +25,11 @@ import User from './entity/user';
password: 'ne5BbDCiYwx3n6nE',
database: 'nest_test',
entities: [User],
synchronize: true,
synchronize: true, // 是否开启同步
autoLoadEntities: true, // 是否自动导入
logging: false, // 打印日志
}),
CatsModule,
],
controllers: [AppController],
providers: [AppService],

0
src/app.service.ts Normal file → Executable file
View File

View File

@@ -0,0 +1,4 @@
import { Module } from '@nestjs/common';
@Module({})
export class CatsModule {}

View File

@@ -0,0 +1,22 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import TechEntity from '../entity/tech';
@Controller('/tech')
@ApiTags('ORM使用')
export default class TechController {
@InjectRepository(TechEntity)
private tech: Repository<TechEntity>;
@Get('/t1')
getT1() {
return 'T1';
}
/// 数据库查询 裙查询
@Get('/t2')
async getT2() {
const techs = await this.tech.find();
return techs;
}
}

View File

@@ -0,0 +1,10 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export default class Tech {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}

10
src/apps/pluginORM/index.ts Executable file
View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import Tech from './entity/tech';
import TechController from './controller/tech';
@Module({
imports: [TypeOrmModule.forFeature([Tech])], // 此模块使用 forFeature() 方法定义在当前范围中注册哪些存储库。这样,我们就可以使用 @InjectRepository()装饰器将 UsersRepository 注入到 UsersService 中:
controllers: [TechController],
providers: [],
})
export class TechModule {}

4
src/apps/pluginRate/README.md Executable file
View File

@@ -0,0 +1,4 @@
# 接口限速插件
pass

View File

@@ -0,0 +1,18 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { RateLimit } from 'nestjs-rate-limiter';
@Controller('rate')
@ApiTags('Rate频率限制')
export default class RateController {
@Get('/t1')
@RateLimit({
keyPrefix: 'sign-up',
points: 1,
duration: 1,
errorMessage: '系统忙',
})
T1() {
return '频率限制T1';
}
}

8
src/apps/pluginRate/index.ts Executable file
View File

@@ -0,0 +1,8 @@
// npm i nestjs-rate-limiter
import { Module } from '@nestjs/common';
import RateController from './controller';
@Module({
controllers: [RateController],
providers: [],
})
export class RateModule {}

View File

@@ -0,0 +1,66 @@
# 集成Swagger
https://docs.nestjs.com/openapi/introduction
要开始使用,首先安装依赖、
$ npm install --save @nestjs/swagger swagger-ui-expressCopy to clipboardErrorCopied
如果使用fastify安装fastify-swagger而不是swagger-ui-express:
$ npm install --save @nestjs/swagger fastify-swagger
安装完成后在main.ts文件中定义并初始化SwaggerModule类:
```js
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import { join } from 'path';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
async function bootstrap() {
console.log(__dirname);
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join(__dirname, '..', 'public'));
app.setBaseViewsDir(join(__dirname, '..', 'templates'));
app.setViewEngine('hbs');
app.useStaticAssets(join(__dirname, '..', 'public'), {
prefix: '/static',
});
const config = new DocumentBuilder()
.setTitle('Nest.js')
.setDescription('使用Nest.js')
.setVersion('1.0')
.addTag('Use Nest.js')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
await app.listen(3000);
}
bootstrap();
```
## 标签
```js
@ApiTags('模板使用')
@Get('/temp1')
@Render('index')
temp1() {
return {
message: 'Hello,,Nest',
};
}
```
## 响应
```js
@ApiResponse({ status: 201, description: 'The record has been successfully created.'})
@ApiResponse({ status: 403, description: 'Forbidden.'})
```

14
src/apps/useCli/README.md Executable file
View File

@@ -0,0 +1,14 @@
# Cli
Nest CLI是一个命令行界面工具以帮助您初始化、开发和维护 Nest 应用程序。它以多种方式提供帮助,包括搭建项目、以开发模式为其提供服务,以及为生产分发构建和打包应用程序。它体现了最佳实践的架构模式,以构建良好的应用程序。
```shell
npm install -g @nestjs/cli
```
```shell
╰─$ nest -v
8.2.6
```

View File

@@ -0,0 +1,2 @@
# Controller

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import ParamController from './param';
@Module({
imports: [],
controllers: [ParamController],
providers: [],
})
export class UseControllerModule {}

51
src/apps/useController/param.ts Executable file
View File

@@ -0,0 +1,51 @@
import { Controller, Get, HttpStatus, Param, Req, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Response, Request } from 'express';
@Controller('/useController')
@ApiTags('Controller使用')
export default class ParamController {
// 基本控制器
@Get('/t1')
getT1() {
return '测试路由';
}
// Get请求参数
@Get('/t2')
getT2() {
return '测试路由';
}
// Post参数
@Get('/t3')
getT3() {
return '测试路由';
}
// Request对象
@Get('/request')
getT4(@Req() request: Request) {
console.log(request);
return {
method: request.method,
url: request.url,
baseUrl: request.baseUrl,
headers: request.headers,
cookies: request.cookies,
statusCode: request.statusCode,
route: request.route,
};
}
// Get路径参数
@Get('/query_param/:name')
getT5(@Param() params) {
console.log(params);
return {
...params,
};
}
/// 自定义Response
@Get('/response')
getT6(@Res() res: Response) {
res.status(HttpStatus.CREATED).send([1, 2, 3]);
}
}

0
src/entity/user.ts Normal file → Executable file
View File

0
src/main.ts Normal file → Executable file
View File

0
templates/index.hbs Normal file → Executable file
View File

View File

@@ -1,24 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});

View File

@@ -1,9 +0,0 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}

0
tsconfig.build.json Normal file → Executable file
View File

0
tsconfig.json Normal file → Executable file
View File

7749
yarn.lock Normal file → Executable file

File diff suppressed because it is too large Load Diff