-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 新增nest模板、新增server类型的vite配置 #4743
Open
MZ-Dlovely
wants to merge
11
commits into
vbenjs:main
Choose a base branch
from
MZ-Dlovely:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+4,219
−872
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
bfd9cbb
feat: 新增nest模板、新增server类型的vite配置
MZ-Dlovely d13a625
feat: 允许使用swc编译, 并提供模板配置
MZ-Dlovely adb6337
feat: 提供JWT验证及鉴权
MZ-Dlovely 82887ca
feat: 提供vben所必需的核心接口
MZ-Dlovely a71934e
Merge branch 'main' of github.com:vbenjs/vue-vben-admin
MZ-Dlovely 6911873
feat: 提供统一响应的过滤器及拦截器
MZ-Dlovely eac4986
feat: 提供后端服务器常用的接口
MZ-Dlovely 5010897
fix: 运行测试,修复接口响应错误的问题
MZ-Dlovely bf0183a
docs: 更新nestjs模版相关文档
MZ-Dlovely 8f7c16e
Merge branch 'main' of github.com:vbenjs/vue-vben-admin
MZ-Dlovely 6ea7a63
chore: changeset
MZ-Dlovely File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
'@vben/backend-nest': patch | ||
'@vben/docs': patch | ||
'@vben/vite-config': patch | ||
--- | ||
|
||
feat: 新增nest模板 | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
feat: 新增server类型的vite配置 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# 适配器 | ||
VITE_ADAPTER=nest | ||
|
||
# 应用名称 | ||
VITE_APP_NAME=Vben Server | ||
|
||
# 应用入口的路径 | ||
VITE_APP_PATH=src | ||
|
||
# 应用入口的导出变量 | ||
VITE_EXPORT_NAME=default | ||
|
||
# 立即启动 | ||
VITE_IMMEDIATE=true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VITE_VISUALIZER=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# 端口号 | ||
VITE_PORT=5320 | ||
|
||
# 是否开启 SWC | ||
VITE_SWC=true | ||
|
||
# JWT密钥 | ||
VITE_JWT_SECRET=your_jwt_secret | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# 端口号 | ||
VITE_PORT=3000 | ||
|
||
# 是否开启 SWC | ||
VITE_SWC=false | ||
|
||
# JWT密钥 | ||
VITE_JWT_SECRET=your_jwt_secret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"explorer.fileNesting.patterns": { | ||
"*.ts": "${capture}.module.ts,${capture}.service.ts,${capture}.dto.ts,${capture}.controller.ts", | ||
"*.module.ts": "${capture}.module.ts,${capture}.service.ts,${capture}.dto.ts", | ||
"*.service.ts": "${capture}.dto.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "@vben/backend-nest", | ||
"version": "0.0.1", | ||
"description": "", | ||
"private": true, | ||
"license": "MIT", | ||
"author": "", | ||
"scripts": { | ||
"build": "pnpm vite build --mode production", | ||
"build:analyze": "pnpm vite build --mode analyze", | ||
"dev": "pnpm vite --mode development", | ||
"preview": "vite preview", | ||
"typecheck": "vue-tsc --noEmit --skipLibCheck" | ||
}, | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"imports": { | ||
"#/*": "./src/*" | ||
}, | ||
"dependencies": { | ||
"@nestjs/common": "^10.0.0", | ||
"@nestjs/core": "^10.0.0", | ||
"@nestjs/jwt": "^10.2.0", | ||
"@nestjs/passport": "^10.0.3", | ||
"@nestjs/platform-express": "^10.0.0", | ||
"@nestjs/swagger": "^8.0.0", | ||
"class-transformer": "^0.5.1", | ||
"class-validator": "^0.14.1", | ||
"cookie-parser": "^1.4.7", | ||
"passport": "^0.7.0", | ||
"passport-jwt": "^4.0.1", | ||
"passport-local": "^1.0.0", | ||
"reflect-metadata": "^0.2.0", | ||
"rxjs": "^7.8.1" | ||
}, | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"devDependencies": { | ||
"@nestjs/cli": "^10.0.0", | ||
"@types/cookie-parser": "^1.4.7", | ||
"@types/express": "^4.17.17", | ||
"@types/node": "catalog:", | ||
"@types/passport-jwt": "^4.0.1", | ||
"@types/passport-local": "^1.0.38" | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { MiddlewareConsumer, NestModule } from '@nestjs/common'; | ||
|
||
import { Module } from '@nestjs/common'; | ||
|
||
import { AuthModule } from '#/auth'; | ||
import filters from '#/filters'; | ||
import guards from '#/guards'; | ||
import interceptors from '#/interceptor'; | ||
import middlewares from '#/middlewares'; | ||
import { RoutesModule } from '#/routes'; | ||
|
||
@Module({ | ||
imports: [RoutesModule, AuthModule], | ||
providers: [...guards, ...interceptors, ...filters], | ||
}) | ||
export class AppModule implements NestModule { | ||
configure(consumer: MiddlewareConsumer) { | ||
consumer.apply(...middlewares).forRoutes('*'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { INestApplication } from '@nestjs/common'; | ||
|
||
import { NestFactory } from '@nestjs/core'; | ||
|
||
import plugins from '#/plugins'; | ||
|
||
import { AppModule } from './index.module'; | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let app: INestApplication; | ||
|
||
async function createApp() { | ||
const app = await NestFactory.create(AppModule); | ||
|
||
app.enableCors(); | ||
|
||
for (const plugin of plugins) { | ||
app.use(plugin); | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return app; | ||
} | ||
|
||
export async function useApp() { | ||
if (!app) { | ||
app = await createApp(); | ||
} | ||
|
||
return app; | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export async function bootstrap() { | ||
const app = await useApp(); | ||
|
||
await app.listen(import.meta.env.VITE_PORT); | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Global, Module } from '@nestjs/common'; | ||
import { JwtModule } from '@nestjs/jwt'; | ||
import { PassportModule } from '@nestjs/passport'; | ||
|
||
import { AuthService } from './index.service'; | ||
import { JwtStrategy } from './jwt.strategy'; | ||
import { LocalStrategy } from './local.strategy'; | ||
|
||
@Module({ | ||
imports: [ | ||
PassportModule, | ||
JwtModule.register({ | ||
global: true, | ||
secret: import.meta.env.VITE_JWT_SECRET, | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}), | ||
], | ||
providers: [AuthService, LocalStrategy, JwtStrategy], | ||
exports: [AuthService], | ||
}) | ||
@Global() | ||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class | ||
export class AuthModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { JwtService } from '@nestjs/jwt'; | ||
|
||
export interface UserInfo { | ||
id: number; | ||
password: string; | ||
realName: string; | ||
roles: string[]; | ||
username: string; | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@Injectable() | ||
export class AuthService { | ||
// TODO: Replace with your own secret key | ||
static ACCESS_TOKEN_SECRET = 'access_token_secret'; | ||
static MOCK_CODES = [ | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// super | ||
{ | ||
codes: ['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010'], | ||
username: 'vben', | ||
}, | ||
{ | ||
// admin | ||
codes: ['AC_100010', 'AC_100020', 'AC_100030'], | ||
username: 'admin', | ||
}, | ||
{ | ||
// user | ||
codes: ['AC_1000001', 'AC_1000002'], | ||
username: 'jack', | ||
}, | ||
]; | ||
static MOCK_USERS: UserInfo[] = [ | ||
{ | ||
id: 0, | ||
password: '123456', | ||
realName: 'Vben', | ||
roles: ['super'], | ||
username: 'vben', | ||
}, | ||
{ | ||
id: 1, | ||
password: '123456', | ||
realName: 'Admin', | ||
roles: ['admin'], | ||
username: 'admin', | ||
}, | ||
{ | ||
id: 2, | ||
password: '123456', | ||
realName: 'Jack', | ||
roles: ['user'], | ||
username: 'jack', | ||
}, | ||
]; | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static REFRESH_TOKEN_SECRET = 'refresh_token_secret'; | ||
|
||
constructor(private readonly JwtService: JwtService) {} | ||
|
||
public getAccessToken(user: UserInfo) { | ||
return this.JwtService.sign(user, { | ||
expiresIn: '7d', | ||
}); | ||
} | ||
|
||
public getRefreshToken(user: UserInfo) { | ||
return this.JwtService.sign(user, { | ||
expiresIn: '30d', | ||
}); | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public async validateUser(username: string, password: string) { | ||
const findUser = AuthService.MOCK_USERS.find( | ||
(item) => item.username === username && item.password === password, | ||
); | ||
|
||
if (!findUser) { | ||
return; | ||
} | ||
|
||
return findUser; | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
declare global { | ||
export namespace Express { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type | ||
export interface User extends UserInfo {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export { AuthModule } from './index.module'; | ||
export { AuthService } from './index.service'; | ||
|
||
export type { UserInfo } from './index.service'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { PassportStrategy } from '@nestjs/passport'; | ||
import { ExtractJwt, Strategy } from 'passport-jwt'; | ||
|
||
@Injectable() | ||
export class JwtStrategy extends PassportStrategy(Strategy) { | ||
constructor() { | ||
super({ | ||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), | ||
ignoreExpiration: false, | ||
secretOrKey: import.meta.env.VITE_JWT_SECRET, | ||
}); | ||
} | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
async validate(payload: any) { | ||
return { ...payload }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { ForbiddenException, Injectable } from '@nestjs/common'; | ||
import { PassportStrategy } from '@nestjs/passport'; | ||
import { Strategy } from 'passport-local'; | ||
|
||
import { AuthService } from './index.service'; | ||
|
||
@Injectable() | ||
export class LocalStrategy extends PassportStrategy(Strategy) { | ||
constructor(private readonly AuthService: AuthService) { | ||
super(); | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
async validate(username: string, password: string): Promise<any> { | ||
const findUser = await this.AuthService.validateUser(username, password); | ||
|
||
if (!findUser) { | ||
throw new ForbiddenException('用户名或密码错误'); | ||
} | ||
|
||
return findUser; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'; | ||
import type { Response } from 'express'; | ||
|
||
import { | ||
BadRequestException, | ||
Catch, | ||
HttpException, | ||
Logger, | ||
} from '@nestjs/common'; | ||
|
||
import { ResponseClass } from '#/interfaces/response'; | ||
|
||
@Catch(HttpException) | ||
export class HttpExceptionFilter implements ExceptionFilter { | ||
private readonly logger = new Logger('HTTP错误响应'); | ||
|
||
catch(exception: HttpException, host: ArgumentsHost) { | ||
const ctx = host.switchToHttp(); | ||
const response = ctx.getResponse<Response>(); | ||
const status = exception.getStatus(); | ||
const results = exception.getResponse() as any; | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// eslint-disable-next-line unicorn/throw-new-error | ||
const result = ResponseClass.Error(results.message); | ||
|
||
// 参数校验错误,默认都是BadRequestException | ||
const isArrayMessage = Array.isArray(results.message); | ||
const isValidationError = | ||
isArrayMessage && | ||
typeof results.message[0] === 'string' && | ||
results.message[0].includes('⓿'); | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (exception instanceof BadRequestException && isValidationError) { | ||
const message: Array<{ field: string; message: Array<string> }> = []; | ||
results.message.forEach((item: string) => { | ||
const [key, val] = item.split('⓿') as [string, string]; | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const findData = message.find((item) => item.field === key); | ||
if (findData) { | ||
findData.message.push(val); | ||
} else { | ||
message.push({ field: key, message: [val] }); | ||
} | ||
}); | ||
|
||
result.error = message; | ||
} | ||
|
||
this.logger.verbose(JSON.stringify(result)); | ||
return response.status(status).json(result); | ||
} | ||
} | ||
|
||
// 默认导出,便于glob导入 | ||
export default HttpExceptionFilter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { ClassProvider, Type } from '@nestjs/common'; | ||
|
||
import { APP_FILTER } from '@nestjs/core'; | ||
|
||
const glob_result = import.meta.glob<Type>('./*.filter.ts', { | ||
import: 'default', | ||
eager: true, | ||
}); | ||
|
||
export default Object.values(glob_result).map<ClassProvider>((useClass) => ({ | ||
provide: APP_FILTER, | ||
useClass, | ||
})); | ||
MZ-Dlovely marked this conversation as resolved.
Show resolved
Hide resolved
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
🛠️ Refactor suggestion
Based on the git history, I can now generate the final response since we have clear evidence that these are indeed new features introduced in this PR (commit bfd9cbb: "feat: 新增nest模板、新增server类型的vite配置").
Version bumps should be minor, not patch, for these new features
The changes introduce entirely new features:
According to semver conventions, new features warrant minor version bumps. Patch versions are for backwards-compatible bug fixes only.
🔗 Analysis chain
Consider using minor version bumps instead of patches.
Since you're adding new features (NestJS template and server-type Vite configuration), these changes should typically warrant minor version bumps rather than patches according to semver conventions. Patch versions are usually reserved for backwards-compatible bug fixes.
Let me gather more information about these packages to verify if they are new additions or existing ones with modifications.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 402
Script:
Length of output: 1041
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anncwb how do u think about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.