[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase":2286,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase":2312},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":13,"pinned":14,"draft":14,"body":15,"seo":2282,"stem":2283,"id":2284,"extension":2285},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","NestJS 是基于 Node.js 的服务端框架，采用 TypeScript、依赖注入 与模块化结构，默认 HTTP 适配器为 Express，可切换 Fastify。见 NestJS 导读、后端入门。","技能小册",[12],"nestjs","2021-03-09",false,{"type":16,"value":17,"toc":2273},"minimark",[18,22,65,70,92,96,121,125,130,169,400,404,419,523,527,544,687,691,716,883,887,915,1137,1141,1175,1352,1356,1382,1524,1528,1548,1764,1768,1784,1947,1954,1957,2057,2061,2211,2214,2218,2221,2269],[19,20,8],"h1",{"id":21},"nestjs-基础",[23,24,25,32,33,37,38,41,42,45,46,49,50,55,56,41,60,64],"p",{},[26,27,31],"a",{"href":28,"rel":29},"https:\u002F\u002Fdocs.nestjs.com\u002F",[30],"nofollow","NestJS"," 是基于 ",[34,35,36],"strong",{},"Node.js"," 的服务端框架，采用 ",[34,39,40],{},"TypeScript","、",[34,43,44],{},"依赖注入"," 与",[34,47,48],{},"模块化","结构，默认 HTTP 适配器为 Express，可切换 ",[26,51,54],{"href":52,"rel":53},"https:\u002F\u002Fdocs.nestjs.com\u002Ftechniques\u002Fperformance",[30],"Fastify","。见 ",[26,57,59],{"href":58},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs","NestJS 导读",[26,61,63],{"href":62},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbasics","后端入门","。",[66,67,69],"h3",{"id":68},"一框架定位","一、框架定位",[71,72,73,80,86],"ul",{},[74,75,76,79],"li",{},[34,77,78],{},"底层 HTTP 引擎","：默认使用 Express，可通过配置切换到 Fastify（性能更高）。",[74,81,82,85],{},[34,83,84],{},"适用场景","：REST API、GraphQL、微服务、WebSocket 应用等。",[74,87,88,91],{},[34,89,90],{},"特点","：提供一套完整的架构约束，使团队开发更规范、代码更具可维护性；与 TypeScript 深度集成，同时也支持纯 JavaScript。",[66,93,95],{"id":94},"二核心设计思想","二、核心设计思想",[97,98,99,104,109,115],"ol",{},[74,100,101,103],{},[34,102,48],{},"：每个应用由多个模块（Module）组成，模块是代码组织的基本单元。",[74,105,106,108],{},[34,107,44],{},"：通过 IoC 容器管理对象之间的依赖关系，提升解耦和测试性。",[74,110,111,114],{},[34,112,113],{},"装饰器模式","：大量使用装饰器（Decorator）来声明路由、依赖、异常处理等，简化元数据定义。",[74,116,117,120],{},[34,118,119],{},"TypeScript 优先","：利用类型系统提升开发体验和代码健壮性，但不强制。",[66,122,124],{"id":123},"三核心构件","三、核心构件",[126,127,129],"h4",{"id":128},"_1-控制器controllers","1. 控制器（Controllers）",[71,131,132,138],{},[74,133,134,137],{},[34,135,136],{},"职责","：接收特定请求，返回响应。不包含业务逻辑，只负责路由调度和视图\u002F数据返回。",[74,139,140,143,144,148,149,41,152,155,156,41,159,41,162,41,165,168],{},[34,141,142],{},"装饰器","：",[145,146,147],"code",{},"@Controller()"," 定义路径前缀；",[145,150,151],{},"@Get()",[145,153,154],{},"@Post()"," 等定义 HTTP 方法；",[145,157,158],{},"@Req()",[145,160,161],{},"@Res()",[145,163,164],{},"@Body()",[145,166,167],{},"@Param()"," 等获取请求参数。",[170,171,176],"pre",{"className":172,"code":173,"language":174,"meta":175,"style":175},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Controller, Get, Post, Body } from \"@nestjs\u002Fcommon\";\n\n@Controller(\"users\")\nexport class UsersController {\n  @Get()\n  findAll(): string {\n    return \"This action returns all users\";\n  }\n\n  @Post()\n  create(@Body() createUserDto: CreateUserDto) {\n    return \"User created\";\n  }\n}\n","ts","",[145,177,178,231,238,261,278,290,310,325,331,336,346,375,389,394],{"__ignoreMap":175},[179,180,183,187,191,195,198,201,203,206,208,211,214,217,221,225,228],"span",{"class":181,"line":182},"line",1,[179,184,186],{"class":185},"sVHd0","import",[179,188,190],{"class":189},"sP7_E"," {",[179,192,194],{"class":193},"su5hD"," Controller",[179,196,197],{"class":189},",",[179,199,200],{"class":193}," Get",[179,202,197],{"class":189},[179,204,205],{"class":193}," Post",[179,207,197],{"class":189},[179,209,210],{"class":193}," Body",[179,212,213],{"class":189}," }",[179,215,216],{"class":185}," from",[179,218,220],{"class":219},"sjJ54"," \"",[179,222,224],{"class":223},"s_sjI","@nestjs\u002Fcommon",[179,226,227],{"class":219},"\"",[179,229,230],{"class":189},";\n",[179,232,234],{"class":181,"line":233},2,[179,235,237],{"emptyLinePlaceholder":236},true,"\n",[179,239,241,244,248,251,253,256,258],{"class":181,"line":240},3,[179,242,243],{"class":189},"@",[179,245,247],{"class":246},"sGLFI","Controller",[179,249,250],{"class":193},"(",[179,252,227],{"class":219},[179,254,255],{"class":223},"users",[179,257,227],{"class":219},[179,259,260],{"class":193},")\n",[179,262,264,267,271,275],{"class":181,"line":263},4,[179,265,266],{"class":185},"export",[179,268,270],{"class":269},"sbsja"," class",[179,272,274],{"class":273},"sbgvK"," UsersController",[179,276,277],{"class":189}," {\n",[179,279,281,284,287],{"class":181,"line":280},5,[179,282,283],{"class":189},"  @",[179,285,286],{"class":246},"Get",[179,288,289],{"class":193},"()\n",[179,291,293,297,300,304,308],{"class":181,"line":292},6,[179,294,296],{"class":295},"sVXei","  findAll",[179,298,299],{"class":189},"()",[179,301,303],{"class":302},"smGrS",":",[179,305,307],{"class":306},"sZMiF"," string",[179,309,277],{"class":189},[179,311,313,316,318,321,323],{"class":181,"line":312},7,[179,314,315],{"class":185},"    return",[179,317,220],{"class":219},[179,319,320],{"class":223},"This action returns all users",[179,322,227],{"class":219},[179,324,230],{"class":189},[179,326,328],{"class":181,"line":327},8,[179,329,330],{"class":189},"  }\n",[179,332,334],{"class":181,"line":333},9,[179,335,237],{"emptyLinePlaceholder":236},[179,337,339,341,344],{"class":181,"line":338},10,[179,340,283],{"class":189},[179,342,343],{"class":246},"Post",[179,345,289],{"class":193},[179,347,349,352,355,358,361,365,367,370,373],{"class":181,"line":348},11,[179,350,351],{"class":295},"  create",[179,353,354],{"class":189},"(@",[179,356,357],{"class":246},"Body",[179,359,360],{"class":193},"() ",[179,362,364],{"class":363},"s99_P","createUserDto",[179,366,303],{"class":302},[179,368,369],{"class":273}," CreateUserDto",[179,371,372],{"class":189},")",[179,374,277],{"class":189},[179,376,378,380,382,385,387],{"class":181,"line":377},12,[179,379,315],{"class":185},[179,381,220],{"class":219},[179,383,384],{"class":223},"User created",[179,386,227],{"class":219},[179,388,230],{"class":189},[179,390,392],{"class":181,"line":391},13,[179,393,330],{"class":189},[179,395,397],{"class":181,"line":396},14,[179,398,399],{"class":189},"}\n",[126,401,403],{"id":402},"_2-提供者providers","2. 提供者（Providers）",[71,405,406,411],{},[74,407,408,410],{},[34,409,136],{},"：实现业务逻辑、数据访问、工具函数等，可以被注入到其他类中（通常是 Service）。",[74,412,413,143,415,418],{},[34,414,142],{},[145,416,417],{},"@Injectable()"," 标记一个类可被依赖注入容器管理。",[170,420,422],{"className":172,"code":421,"language":174,"meta":175,"style":175},"import { Injectable } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class UsersService {\n  findOne(id: number) {\n    return { id, name: \"John\" };\n  }\n}\n",[145,423,424,445,449,458,469,488,515,519],{"__ignoreMap":175},[179,425,426,428,430,433,435,437,439,441,443],{"class":181,"line":182},[179,427,186],{"class":185},[179,429,190],{"class":189},[179,431,432],{"class":193}," Injectable",[179,434,213],{"class":189},[179,436,216],{"class":185},[179,438,220],{"class":219},[179,440,224],{"class":223},[179,442,227],{"class":219},[179,444,230],{"class":189},[179,446,447],{"class":181,"line":233},[179,448,237],{"emptyLinePlaceholder":236},[179,450,451,453,456],{"class":181,"line":240},[179,452,243],{"class":189},[179,454,455],{"class":246},"Injectable",[179,457,289],{"class":193},[179,459,460,462,464,467],{"class":181,"line":263},[179,461,266],{"class":185},[179,463,270],{"class":269},[179,465,466],{"class":273}," UsersService",[179,468,277],{"class":189},[179,470,471,474,476,479,481,484,486],{"class":181,"line":280},[179,472,473],{"class":295},"  findOne",[179,475,250],{"class":189},[179,477,478],{"class":363},"id",[179,480,303],{"class":302},[179,482,483],{"class":306}," number",[179,485,372],{"class":189},[179,487,277],{"class":189},[179,489,490,492,494,497,499,503,505,507,510,512],{"class":181,"line":292},[179,491,315],{"class":185},[179,493,190],{"class":189},[179,495,496],{"class":193}," id",[179,498,197],{"class":189},[179,500,502],{"class":501},"skxfh"," name",[179,504,303],{"class":189},[179,506,220],{"class":219},[179,508,509],{"class":223},"John",[179,511,227],{"class":219},[179,513,514],{"class":189}," };\n",[179,516,517],{"class":181,"line":312},[179,518,330],{"class":189},[179,520,521],{"class":181,"line":327},[179,522,399],{"class":189},[126,524,526],{"id":525},"_3-模块modules","3. 模块（Modules）",[71,528,529,537],{},[74,530,531,533,534,64],{},[34,532,136],{},"：将相关的控制器、提供者、其他模块组织在一起。每个应用至少有一个根模块 ",[145,535,536],{},"AppModule",[74,538,539,143,541,64],{},[34,540,142],{},[145,542,543],{},"@Module({ imports, controllers, providers, exports })",[170,545,547],{"className":172,"code":546,"language":174,"meta":175,"style":175},"import { Module } from \"@nestjs\u002Fcommon\";\nimport { UsersController } from \".\u002Fusers.controller\";\nimport { UsersService } from \".\u002Fusers.service\";\n\n@Module({\n  controllers: [UsersController],\n  providers: [UsersService],\n  exports: [UsersService], \u002F\u002F 允许其他模块导入本模块的提供者\n})\nexport class UsersModule {}\n",[145,548,549,570,591,612,616,628,641,653,668,675],{"__ignoreMap":175},[179,550,551,553,555,558,560,562,564,566,568],{"class":181,"line":182},[179,552,186],{"class":185},[179,554,190],{"class":189},[179,556,557],{"class":193}," Module",[179,559,213],{"class":189},[179,561,216],{"class":185},[179,563,220],{"class":219},[179,565,224],{"class":223},[179,567,227],{"class":219},[179,569,230],{"class":189},[179,571,572,574,576,578,580,582,584,587,589],{"class":181,"line":233},[179,573,186],{"class":185},[179,575,190],{"class":189},[179,577,274],{"class":193},[179,579,213],{"class":189},[179,581,216],{"class":185},[179,583,220],{"class":219},[179,585,586],{"class":223},".\u002Fusers.controller",[179,588,227],{"class":219},[179,590,230],{"class":189},[179,592,593,595,597,599,601,603,605,608,610],{"class":181,"line":240},[179,594,186],{"class":185},[179,596,190],{"class":189},[179,598,466],{"class":193},[179,600,213],{"class":189},[179,602,216],{"class":185},[179,604,220],{"class":219},[179,606,607],{"class":223},".\u002Fusers.service",[179,609,227],{"class":219},[179,611,230],{"class":189},[179,613,614],{"class":181,"line":263},[179,615,237],{"emptyLinePlaceholder":236},[179,617,618,620,623,625],{"class":181,"line":280},[179,619,243],{"class":189},[179,621,622],{"class":246},"Module",[179,624,250],{"class":193},[179,626,627],{"class":189},"{\n",[179,629,630,633,635,638],{"class":181,"line":292},[179,631,632],{"class":501},"  controllers",[179,634,303],{"class":189},[179,636,637],{"class":193}," [UsersController]",[179,639,640],{"class":189},",\n",[179,642,643,646,648,651],{"class":181,"line":312},[179,644,645],{"class":501},"  providers",[179,647,303],{"class":189},[179,649,650],{"class":193}," [UsersService]",[179,652,640],{"class":189},[179,654,655,658,660,662,664],{"class":181,"line":327},[179,656,657],{"class":501},"  exports",[179,659,303],{"class":189},[179,661,650],{"class":193},[179,663,197],{"class":189},[179,665,667],{"class":666},"sutJx"," \u002F\u002F 允许其他模块导入本模块的提供者\n",[179,669,670,673],{"class":181,"line":333},[179,671,672],{"class":189},"}",[179,674,260],{"class":193},[179,676,677,679,681,684],{"class":181,"line":338},[179,678,266],{"class":185},[179,680,270],{"class":269},[179,682,683],{"class":273}," UsersModule",[179,685,686],{"class":189}," {}\n",[126,688,690],{"id":689},"_4-中间件middleware","4. 中间件（Middleware）",[71,692,693,706],{},[74,694,695,697,698,701,702,705],{},[34,696,136],{},"：在路由处理器",[34,699,700],{},"之前","执行，常用于日志、请求解析、跨域等。可以基于函数或实现 ",[145,703,704],{},"NestMiddleware"," 接口的类。",[74,707,708,711,712,715],{},[34,709,710],{},"注册","：在模块配置中实现 ",[145,713,714],{},"configure"," 方法或全局注册。",[170,717,719],{"className":172,"code":718,"language":174,"meta":175,"style":175},"import { Injectable, NestMiddleware } from \"@nestjs\u002Fcommon\";\nimport { Request, Response, NextFunction } from \"express\";\n\n@Injectable()\nexport class LoggerMiddleware implements NestMiddleware {\n  use(req: Request, res: Response, next: NextFunction) {\n    console.log(\"Request...\");\n    next();\n  }\n}\n",[145,720,721,746,778,782,790,806,842,866,875,879],{"__ignoreMap":175},[179,722,723,725,727,729,731,734,736,738,740,742,744],{"class":181,"line":182},[179,724,186],{"class":185},[179,726,190],{"class":189},[179,728,432],{"class":193},[179,730,197],{"class":189},[179,732,733],{"class":193}," NestMiddleware",[179,735,213],{"class":189},[179,737,216],{"class":185},[179,739,220],{"class":219},[179,741,224],{"class":223},[179,743,227],{"class":219},[179,745,230],{"class":189},[179,747,748,750,752,755,757,760,762,765,767,769,771,774,776],{"class":181,"line":233},[179,749,186],{"class":185},[179,751,190],{"class":189},[179,753,754],{"class":193}," Request",[179,756,197],{"class":189},[179,758,759],{"class":193}," Response",[179,761,197],{"class":189},[179,763,764],{"class":193}," NextFunction",[179,766,213],{"class":189},[179,768,216],{"class":185},[179,770,220],{"class":219},[179,772,773],{"class":223},"express",[179,775,227],{"class":219},[179,777,230],{"class":189},[179,779,780],{"class":181,"line":240},[179,781,237],{"emptyLinePlaceholder":236},[179,783,784,786,788],{"class":181,"line":263},[179,785,243],{"class":189},[179,787,455],{"class":246},[179,789,289],{"class":193},[179,791,792,794,796,799,802,804],{"class":181,"line":280},[179,793,266],{"class":185},[179,795,270],{"class":269},[179,797,798],{"class":273}," LoggerMiddleware",[179,800,801],{"class":269}," implements",[179,803,733],{"class":273},[179,805,277],{"class":189},[179,807,808,811,813,816,818,820,822,825,827,829,831,834,836,838,840],{"class":181,"line":292},[179,809,810],{"class":295},"  use",[179,812,250],{"class":189},[179,814,815],{"class":363},"req",[179,817,303],{"class":302},[179,819,754],{"class":273},[179,821,197],{"class":189},[179,823,824],{"class":363}," res",[179,826,303],{"class":302},[179,828,759],{"class":273},[179,830,197],{"class":189},[179,832,833],{"class":363}," next",[179,835,303],{"class":302},[179,837,764],{"class":273},[179,839,372],{"class":189},[179,841,277],{"class":189},[179,843,844,847,850,853,855,857,860,862,864],{"class":181,"line":312},[179,845,846],{"class":193},"    console",[179,848,849],{"class":189},".",[179,851,852],{"class":246},"log",[179,854,250],{"class":501},[179,856,227],{"class":219},[179,858,859],{"class":223},"Request...",[179,861,227],{"class":219},[179,863,372],{"class":501},[179,865,230],{"class":189},[179,867,868,871,873],{"class":181,"line":327},[179,869,870],{"class":246},"    next",[179,872,299],{"class":501},[179,874,230],{"class":189},[179,876,877],{"class":181,"line":333},[179,878,330],{"class":189},[179,880,881],{"class":181,"line":338},[179,882,399],{"class":189},[126,884,886],{"id":885},"_5-异常过滤器exception-filters","5. 异常过滤器（Exception Filters）",[71,888,889,894,903],{},[74,890,891,893],{},[34,892,136],{},"：捕获应用中的异常，自定义返回格式和状态码。",[74,895,896,143,899,902],{},[34,897,898],{},"内置过滤器",[145,900,901],{},"HttpException"," 及其子类；可创建自定义异常过滤器。",[74,904,905,143,907,910,911,914],{},[34,906,142],{},[145,908,909],{},"@Catch()"," 指定捕获的异常类型；",[145,912,913],{},"@UseFilters()"," 绑定到控制器或方法。",[170,916,918],{"className":172,"code":917,"language":174,"meta":175,"style":175},"import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from \"@nestjs\u002Fcommon\";\n\n@Catch(HttpException)\nexport class HttpExceptionFilter implements ExceptionFilter {\n  catch(exception: HttpException, host: ArgumentsHost) {\n    const ctx = host.switchToHttp();\n    const response = ctx.getResponse();\n    response.status(exception.getStatus()).json({\n      statusCode: exception.getStatus(),\n      message: exception.message,\n    });\n  }\n}\n",[145,919,920,956,960,970,985,1012,1035,1055,1086,1104,1120,1129,1133],{"__ignoreMap":175},[179,921,922,924,926,929,931,934,936,939,941,944,946,948,950,952,954],{"class":181,"line":182},[179,923,186],{"class":185},[179,925,190],{"class":189},[179,927,928],{"class":193}," ExceptionFilter",[179,930,197],{"class":189},[179,932,933],{"class":193}," Catch",[179,935,197],{"class":189},[179,937,938],{"class":193}," ArgumentsHost",[179,940,197],{"class":189},[179,942,943],{"class":193}," HttpException",[179,945,213],{"class":189},[179,947,216],{"class":185},[179,949,220],{"class":219},[179,951,224],{"class":223},[179,953,227],{"class":219},[179,955,230],{"class":189},[179,957,958],{"class":181,"line":233},[179,959,237],{"emptyLinePlaceholder":236},[179,961,962,964,967],{"class":181,"line":240},[179,963,243],{"class":189},[179,965,966],{"class":246},"Catch",[179,968,969],{"class":193},"(HttpException)\n",[179,971,972,974,976,979,981,983],{"class":181,"line":263},[179,973,266],{"class":185},[179,975,270],{"class":269},[179,977,978],{"class":273}," HttpExceptionFilter",[179,980,801],{"class":269},[179,982,928],{"class":273},[179,984,277],{"class":189},[179,986,987,990,992,995,997,999,1001,1004,1006,1008,1010],{"class":181,"line":280},[179,988,989],{"class":295},"  catch",[179,991,250],{"class":189},[179,993,994],{"class":363},"exception",[179,996,303],{"class":302},[179,998,943],{"class":273},[179,1000,197],{"class":189},[179,1002,1003],{"class":363}," host",[179,1005,303],{"class":302},[179,1007,938],{"class":273},[179,1009,372],{"class":189},[179,1011,277],{"class":189},[179,1013,1014,1017,1021,1024,1026,1028,1031,1033],{"class":181,"line":292},[179,1015,1016],{"class":269},"    const",[179,1018,1020],{"class":1019},"s_hVV"," ctx",[179,1022,1023],{"class":302}," =",[179,1025,1003],{"class":193},[179,1027,849],{"class":189},[179,1029,1030],{"class":246},"switchToHttp",[179,1032,299],{"class":501},[179,1034,230],{"class":189},[179,1036,1037,1039,1042,1044,1046,1048,1051,1053],{"class":181,"line":312},[179,1038,1016],{"class":269},[179,1040,1041],{"class":1019}," response",[179,1043,1023],{"class":302},[179,1045,1020],{"class":193},[179,1047,849],{"class":189},[179,1049,1050],{"class":246},"getResponse",[179,1052,299],{"class":501},[179,1054,230],{"class":189},[179,1056,1057,1060,1062,1065,1067,1069,1071,1074,1077,1079,1082,1084],{"class":181,"line":327},[179,1058,1059],{"class":193},"    response",[179,1061,849],{"class":189},[179,1063,1064],{"class":246},"status",[179,1066,250],{"class":501},[179,1068,994],{"class":193},[179,1070,849],{"class":189},[179,1072,1073],{"class":246},"getStatus",[179,1075,1076],{"class":501},"())",[179,1078,849],{"class":189},[179,1080,1081],{"class":246},"json",[179,1083,250],{"class":501},[179,1085,627],{"class":189},[179,1087,1088,1091,1093,1096,1098,1100,1102],{"class":181,"line":333},[179,1089,1090],{"class":501},"      statusCode",[179,1092,303],{"class":189},[179,1094,1095],{"class":193}," exception",[179,1097,849],{"class":189},[179,1099,1073],{"class":246},[179,1101,299],{"class":501},[179,1103,640],{"class":189},[179,1105,1106,1109,1111,1113,1115,1118],{"class":181,"line":338},[179,1107,1108],{"class":501},"      message",[179,1110,303],{"class":189},[179,1112,1095],{"class":193},[179,1114,849],{"class":189},[179,1116,1117],{"class":193},"message",[179,1119,640],{"class":189},[179,1121,1122,1125,1127],{"class":181,"line":348},[179,1123,1124],{"class":189},"    }",[179,1126,372],{"class":501},[179,1128,230],{"class":189},[179,1130,1131],{"class":181,"line":377},[179,1132,330],{"class":189},[179,1134,1135],{"class":181,"line":391},[179,1136,399],{"class":189},[126,1138,1140],{"id":1139},"_6-管道pipes","6. 管道（Pipes）",[71,1142,1143,1152,1165],{},[74,1144,1145,1147,1148,1151],{},[34,1146,136],{},"：对请求参数进行",[34,1149,1150],{},"验证和转换","（例如将字符串转为数字，验证 DTO 约束）。",[74,1153,1154,143,1157,1160,1161,1164],{},[34,1155,1156],{},"常用内置管道",[145,1158,1159],{},"ValidationPipe","（配合 class-validator）、",[145,1162,1163],{},"ParseIntPipe"," 等。",[74,1166,1167,1170,1171,1174],{},[34,1168,1169],{},"自定义管道","：实现 ",[145,1172,1173],{},"PipeTransform"," 接口。",[170,1176,1178],{"className":172,"code":1177,"language":174,"meta":175,"style":175},"import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class ParseIdPipe implements PipeTransform {\n  transform(value: any, metadata: ArgumentMetadata) {\n    const val = parseInt(value, 10);\n    if (isNaN(val)) throw new BadRequestException(\"Validation failed\");\n    return val;\n  }\n}\n",[145,1179,1180,1215,1219,1227,1242,1270,1296,1336,1344,1348],{"__ignoreMap":175},[179,1181,1182,1184,1186,1189,1191,1193,1195,1198,1200,1203,1205,1207,1209,1211,1213],{"class":181,"line":182},[179,1183,186],{"class":185},[179,1185,190],{"class":189},[179,1187,1188],{"class":193}," PipeTransform",[179,1190,197],{"class":189},[179,1192,432],{"class":193},[179,1194,197],{"class":189},[179,1196,1197],{"class":193}," ArgumentMetadata",[179,1199,197],{"class":189},[179,1201,1202],{"class":193}," BadRequestException",[179,1204,213],{"class":189},[179,1206,216],{"class":185},[179,1208,220],{"class":219},[179,1210,224],{"class":223},[179,1212,227],{"class":219},[179,1214,230],{"class":189},[179,1216,1217],{"class":181,"line":233},[179,1218,237],{"emptyLinePlaceholder":236},[179,1220,1221,1223,1225],{"class":181,"line":240},[179,1222,243],{"class":189},[179,1224,455],{"class":246},[179,1226,289],{"class":193},[179,1228,1229,1231,1233,1236,1238,1240],{"class":181,"line":263},[179,1230,266],{"class":185},[179,1232,270],{"class":269},[179,1234,1235],{"class":273}," ParseIdPipe",[179,1237,801],{"class":269},[179,1239,1188],{"class":273},[179,1241,277],{"class":189},[179,1243,1244,1247,1249,1252,1254,1257,1259,1262,1264,1266,1268],{"class":181,"line":280},[179,1245,1246],{"class":295},"  transform",[179,1248,250],{"class":189},[179,1250,1251],{"class":363},"value",[179,1253,303],{"class":302},[179,1255,1256],{"class":306}," any",[179,1258,197],{"class":189},[179,1260,1261],{"class":363}," metadata",[179,1263,303],{"class":302},[179,1265,1197],{"class":273},[179,1267,372],{"class":189},[179,1269,277],{"class":189},[179,1271,1272,1274,1277,1279,1282,1284,1286,1288,1292,1294],{"class":181,"line":292},[179,1273,1016],{"class":269},[179,1275,1276],{"class":1019}," val",[179,1278,1023],{"class":302},[179,1280,1281],{"class":246}," parseInt",[179,1283,250],{"class":501},[179,1285,1251],{"class":193},[179,1287,197],{"class":189},[179,1289,1291],{"class":1290},"srdBf"," 10",[179,1293,372],{"class":501},[179,1295,230],{"class":189},[179,1297,1298,1301,1304,1307,1309,1312,1315,1318,1321,1323,1325,1327,1330,1332,1334],{"class":181,"line":312},[179,1299,1300],{"class":185},"    if",[179,1302,1303],{"class":501}," (",[179,1305,1306],{"class":246},"isNaN",[179,1308,250],{"class":501},[179,1310,1311],{"class":193},"val",[179,1313,1314],{"class":501},")) ",[179,1316,1317],{"class":185},"throw",[179,1319,1320],{"class":302}," new",[179,1322,1202],{"class":246},[179,1324,250],{"class":501},[179,1326,227],{"class":219},[179,1328,1329],{"class":223},"Validation failed",[179,1331,227],{"class":219},[179,1333,372],{"class":501},[179,1335,230],{"class":189},[179,1337,1338,1340,1342],{"class":181,"line":327},[179,1339,315],{"class":185},[179,1341,1276],{"class":193},[179,1343,230],{"class":189},[179,1345,1346],{"class":181,"line":333},[179,1347,330],{"class":189},[179,1349,1350],{"class":181,"line":338},[179,1351,399],{"class":189},[126,1353,1355],{"id":1354},"_7-守卫guards","7. 守卫（Guards）",[71,1357,1358,1367],{},[74,1359,1360,1362,1363,1366],{},[34,1361,136],{},"：决定请求是否被处理，通常用于",[34,1364,1365],{},"鉴权和授权","。与中间件不同，守卫可以访问执行上下文，知道当前调用的是哪个控制器\u002F方法。",[74,1368,1369,143,1371,1373,1374,1377,1378,1381],{},[34,1370,142],{},[145,1372,417],{}," 实现 ",[145,1375,1376],{},"CanActivate"," 接口；",[145,1379,1380],{},"@UseGuards()"," 绑定。",[170,1383,1385],{"className":172,"code":1384,"language":174,"meta":175,"style":175},"import { Injectable, CanActivate, ExecutionContext } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class AuthGuard implements CanActivate {\n  canActivate(context: ExecutionContext): boolean {\n    const request = context.switchToHttp().getRequest();\n    return !!request.headers.authorization;\n  }\n}\n",[145,1386,1387,1417,1421,1429,1444,1467,1494,1516,1520],{"__ignoreMap":175},[179,1388,1389,1391,1393,1395,1397,1400,1402,1405,1407,1409,1411,1413,1415],{"class":181,"line":182},[179,1390,186],{"class":185},[179,1392,190],{"class":189},[179,1394,432],{"class":193},[179,1396,197],{"class":189},[179,1398,1399],{"class":193}," CanActivate",[179,1401,197],{"class":189},[179,1403,1404],{"class":193}," ExecutionContext",[179,1406,213],{"class":189},[179,1408,216],{"class":185},[179,1410,220],{"class":219},[179,1412,224],{"class":223},[179,1414,227],{"class":219},[179,1416,230],{"class":189},[179,1418,1419],{"class":181,"line":233},[179,1420,237],{"emptyLinePlaceholder":236},[179,1422,1423,1425,1427],{"class":181,"line":240},[179,1424,243],{"class":189},[179,1426,455],{"class":246},[179,1428,289],{"class":193},[179,1430,1431,1433,1435,1438,1440,1442],{"class":181,"line":263},[179,1432,266],{"class":185},[179,1434,270],{"class":269},[179,1436,1437],{"class":273}," AuthGuard",[179,1439,801],{"class":269},[179,1441,1399],{"class":273},[179,1443,277],{"class":189},[179,1445,1446,1449,1451,1454,1456,1458,1460,1462,1465],{"class":181,"line":280},[179,1447,1448],{"class":295},"  canActivate",[179,1450,250],{"class":189},[179,1452,1453],{"class":363},"context",[179,1455,303],{"class":302},[179,1457,1404],{"class":273},[179,1459,372],{"class":189},[179,1461,303],{"class":302},[179,1463,1464],{"class":306}," boolean",[179,1466,277],{"class":189},[179,1468,1469,1471,1474,1476,1479,1481,1483,1485,1487,1490,1492],{"class":181,"line":292},[179,1470,1016],{"class":269},[179,1472,1473],{"class":1019}," request",[179,1475,1023],{"class":302},[179,1477,1478],{"class":193}," context",[179,1480,849],{"class":189},[179,1482,1030],{"class":246},[179,1484,299],{"class":501},[179,1486,849],{"class":189},[179,1488,1489],{"class":246},"getRequest",[179,1491,299],{"class":501},[179,1493,230],{"class":189},[179,1495,1496,1498,1501,1504,1506,1509,1511,1514],{"class":181,"line":312},[179,1497,315],{"class":185},[179,1499,1500],{"class":302}," !!",[179,1502,1503],{"class":193},"request",[179,1505,849],{"class":189},[179,1507,1508],{"class":193},"headers",[179,1510,849],{"class":189},[179,1512,1513],{"class":193},"authorization",[179,1515,230],{"class":189},[179,1517,1518],{"class":181,"line":327},[179,1519,330],{"class":189},[179,1521,1522],{"class":181,"line":333},[179,1523,399],{"class":189},[126,1525,1527],{"id":1526},"_8-拦截器interceptors","8. 拦截器（Interceptors）",[71,1529,1530,1535],{},[74,1531,1532,1534],{},[34,1533,136],{},"：在请求前\u002F后执行额外逻辑：响应映射、日志、超时处理、缓存等。可以改变返回结果。",[74,1536,1537,1170,1540,1543,1544,1547],{},[34,1538,1539],{},"接口",[145,1541,1542],{},"NestInterceptor"," 的 ",[145,1545,1546],{},"intercept"," 方法。",[170,1549,1551],{"className":172,"code":1550,"language":174,"meta":175,"style":175},"import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from \"@nestjs\u002Fcommon\";\nimport { Observable } from \"rxjs\";\nimport { map } from \"rxjs\u002Foperators\";\n\n@Injectable()\nexport class TransformInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    return next.handle().pipe(map((data) => ({ data, status: 200 })));\n  }\n}\n",[145,1552,1553,1587,1609,1631,1635,1643,1658,1696,1756,1760],{"__ignoreMap":175},[179,1554,1555,1557,1559,1561,1563,1566,1568,1570,1572,1575,1577,1579,1581,1583,1585],{"class":181,"line":182},[179,1556,186],{"class":185},[179,1558,190],{"class":189},[179,1560,432],{"class":193},[179,1562,197],{"class":189},[179,1564,1565],{"class":193}," NestInterceptor",[179,1567,197],{"class":189},[179,1569,1404],{"class":193},[179,1571,197],{"class":189},[179,1573,1574],{"class":193}," CallHandler",[179,1576,213],{"class":189},[179,1578,216],{"class":185},[179,1580,220],{"class":219},[179,1582,224],{"class":223},[179,1584,227],{"class":219},[179,1586,230],{"class":189},[179,1588,1589,1591,1593,1596,1598,1600,1602,1605,1607],{"class":181,"line":233},[179,1590,186],{"class":185},[179,1592,190],{"class":189},[179,1594,1595],{"class":193}," Observable",[179,1597,213],{"class":189},[179,1599,216],{"class":185},[179,1601,220],{"class":219},[179,1603,1604],{"class":223},"rxjs",[179,1606,227],{"class":219},[179,1608,230],{"class":189},[179,1610,1611,1613,1615,1618,1620,1622,1624,1627,1629],{"class":181,"line":240},[179,1612,186],{"class":185},[179,1614,190],{"class":189},[179,1616,1617],{"class":193}," map",[179,1619,213],{"class":189},[179,1621,216],{"class":185},[179,1623,220],{"class":219},[179,1625,1626],{"class":223},"rxjs\u002Foperators",[179,1628,227],{"class":219},[179,1630,230],{"class":189},[179,1632,1633],{"class":181,"line":263},[179,1634,237],{"emptyLinePlaceholder":236},[179,1636,1637,1639,1641],{"class":181,"line":280},[179,1638,243],{"class":189},[179,1640,455],{"class":246},[179,1642,289],{"class":193},[179,1644,1645,1647,1649,1652,1654,1656],{"class":181,"line":292},[179,1646,266],{"class":185},[179,1648,270],{"class":269},[179,1650,1651],{"class":273}," TransformInterceptor",[179,1653,801],{"class":269},[179,1655,1565],{"class":273},[179,1657,277],{"class":189},[179,1659,1660,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683,1685,1688,1691,1694],{"class":181,"line":312},[179,1661,1662],{"class":295},"  intercept",[179,1664,250],{"class":189},[179,1666,1453],{"class":363},[179,1668,303],{"class":302},[179,1670,1404],{"class":273},[179,1672,197],{"class":189},[179,1674,833],{"class":363},[179,1676,303],{"class":302},[179,1678,1574],{"class":273},[179,1680,372],{"class":189},[179,1682,303],{"class":302},[179,1684,1595],{"class":273},[179,1686,1687],{"class":189},"\u003C",[179,1689,1690],{"class":306},"any",[179,1692,1693],{"class":189},">",[179,1695,277],{"class":189},[179,1697,1698,1700,1702,1704,1707,1709,1711,1714,1716,1719,1721,1723,1726,1728,1731,1733,1736,1739,1741,1744,1746,1749,1751,1754],{"class":181,"line":327},[179,1699,315],{"class":185},[179,1701,833],{"class":193},[179,1703,849],{"class":189},[179,1705,1706],{"class":246},"handle",[179,1708,299],{"class":501},[179,1710,849],{"class":189},[179,1712,1713],{"class":246},"pipe",[179,1715,250],{"class":501},[179,1717,1718],{"class":246},"map",[179,1720,250],{"class":501},[179,1722,250],{"class":189},[179,1724,1725],{"class":363},"data",[179,1727,372],{"class":189},[179,1729,1730],{"class":269}," =>",[179,1732,1303],{"class":501},[179,1734,1735],{"class":189},"{",[179,1737,1738],{"class":193}," data",[179,1740,197],{"class":189},[179,1742,1743],{"class":501}," status",[179,1745,303],{"class":189},[179,1747,1748],{"class":1290}," 200",[179,1750,213],{"class":189},[179,1752,1753],{"class":501},")))",[179,1755,230],{"class":189},[179,1757,1758],{"class":181,"line":333},[179,1759,330],{"class":189},[179,1761,1762],{"class":181,"line":338},[179,1763,399],{"class":189},[126,1765,1767],{"id":1766},"_9-自定义装饰器custom-decorators","9. 自定义装饰器（Custom Decorators）",[71,1769,1770,1775],{},[74,1771,1772,1774],{},[34,1773,136],{},"：封装重复的逻辑，创建可复用的参数装饰器或方法装饰器。",[74,1776,1777,143,1780,1783],{},[34,1778,1779],{},"工具",[145,1781,1782],{},"createParamDecorator"," 或普通装饰器工厂。",[170,1785,1787],{"className":172,"code":1786,"language":174,"meta":175,"style":175},"import { createParamDecorator, ExecutionContext } from '@nestjs\u002Fcommon';\n\nexport const User = createParamDecorator((data: unknown, ctx: ExecutionContext) => {\n  const request = ctx.switchToHttp().getRequest();\n  return request.user;\n});\n\n\u002F\u002F 在控制器中使用\n@Get()\nasync findOne(@User() user: UserEntity) { ... }\n",[145,1788,1789,1816,1820,1859,1884,1898,1906,1910,1915,1923],{"__ignoreMap":175},[179,1790,1791,1793,1795,1798,1800,1802,1804,1806,1809,1811,1814],{"class":181,"line":182},[179,1792,186],{"class":185},[179,1794,190],{"class":189},[179,1796,1797],{"class":193}," createParamDecorator",[179,1799,197],{"class":189},[179,1801,1404],{"class":193},[179,1803,213],{"class":189},[179,1805,216],{"class":185},[179,1807,1808],{"class":219}," '",[179,1810,224],{"class":223},[179,1812,1813],{"class":219},"'",[179,1815,230],{"class":189},[179,1817,1818],{"class":181,"line":233},[179,1819,237],{"emptyLinePlaceholder":236},[179,1821,1822,1824,1827,1830,1832,1834,1836,1838,1840,1842,1845,1847,1849,1851,1853,1855,1857],{"class":181,"line":240},[179,1823,266],{"class":185},[179,1825,1826],{"class":269}," const",[179,1828,1829],{"class":1019}," User",[179,1831,1023],{"class":302},[179,1833,1797],{"class":246},[179,1835,250],{"class":193},[179,1837,250],{"class":189},[179,1839,1725],{"class":363},[179,1841,303],{"class":302},[179,1843,1844],{"class":306}," unknown",[179,1846,197],{"class":189},[179,1848,1020],{"class":363},[179,1850,303],{"class":302},[179,1852,1404],{"class":273},[179,1854,372],{"class":189},[179,1856,1730],{"class":269},[179,1858,277],{"class":189},[179,1860,1861,1864,1866,1868,1870,1872,1874,1876,1878,1880,1882],{"class":181,"line":263},[179,1862,1863],{"class":269},"  const",[179,1865,1473],{"class":1019},[179,1867,1023],{"class":302},[179,1869,1020],{"class":193},[179,1871,849],{"class":189},[179,1873,1030],{"class":246},[179,1875,299],{"class":501},[179,1877,849],{"class":189},[179,1879,1489],{"class":246},[179,1881,299],{"class":501},[179,1883,230],{"class":189},[179,1885,1886,1889,1891,1893,1896],{"class":181,"line":280},[179,1887,1888],{"class":185},"  return",[179,1890,1473],{"class":193},[179,1892,849],{"class":189},[179,1894,1895],{"class":193},"user",[179,1897,230],{"class":189},[179,1899,1900,1902,1904],{"class":181,"line":292},[179,1901,672],{"class":189},[179,1903,372],{"class":193},[179,1905,230],{"class":189},[179,1907,1908],{"class":181,"line":312},[179,1909,237],{"emptyLinePlaceholder":236},[179,1911,1912],{"class":181,"line":327},[179,1913,1914],{"class":666},"\u002F\u002F 在控制器中使用\n",[179,1916,1917,1919,1921],{"class":181,"line":333},[179,1918,243],{"class":189},[179,1920,286],{"class":246},[179,1922,289],{"class":193},[179,1924,1925,1928,1931,1933,1936,1939,1941,1944],{"class":181,"line":338},[179,1926,1927],{"class":193},"async ",[179,1929,1930],{"class":246},"findOne",[179,1932,354],{"class":193},[179,1934,1935],{"class":246},"User",[179,1937,1938],{"class":193},"() user: UserEntity) ",[179,1940,1735],{"class":189},[179,1942,1943],{"class":302}," ...",[179,1945,1946],{"class":189}," }\n",[66,1948,1950,1951],{"id":1949},"四cli-工具-nestjscli","四、CLI 工具 ",[145,1952,1953],{},"@nestjs\u002Fcli",[23,1955,1956],{},"NestJS 提供了强大的命令行工具，显著提升开发效率。",[1958,1959,1960,1973],"table",{},[1961,1962,1963],"thead",{},[1964,1965,1966,1970],"tr",{},[1967,1968,1969],"th",{},"命令",[1967,1971,1972],{},"作用",[1974,1975,1976,1987,1997,2007,2017,2027,2037,2047],"tbody",{},[1964,1977,1978,1984],{},[1979,1980,1981],"td",{},[145,1982,1983],{},"nest new project-name",[1979,1985,1986],{},"创建新项目（内置多种包管理器选择）",[1964,1988,1989,1994],{},[1979,1990,1991],{},[145,1992,1993],{},"nest generate module \u003Cname>",[1979,1995,1996],{},"生成模块文件",[1964,1998,1999,2004],{},[1979,2000,2001],{},[145,2002,2003],{},"nest generate controller \u003Cname>",[1979,2005,2006],{},"生成控制器文件（自动更新模块）",[1964,2008,2009,2014],{},[1979,2010,2011],{},[145,2012,2013],{},"nest generate service \u003Cname>",[1979,2015,2016],{},"生成服务文件",[1964,2018,2019,2024],{},[1979,2020,2021],{},[145,2022,2023],{},"nest generate resource \u003Cname>",[1979,2025,2026],{},"生成完整的 REST 或 GraphQL 资源（包括模块、控制器、服务、DTO、实体等）",[1964,2028,2029,2034],{},[1979,2030,2031],{},[145,2032,2033],{},"nest start",[1979,2035,2036],{},"启动开发服务器（支持热重载）",[1964,2038,2039,2044],{},[1979,2040,2041],{},[145,2042,2043],{},"nest build",[1979,2045,2046],{},"构建生产代码（输出到 dist 目录）",[1964,2048,2049,2054],{},[1979,2050,2051],{},[145,2052,2053],{},"nest info",[1979,2055,2056],{},"查看当前环境信息",[66,2058,2060],{"id":2059},"五总结","五、总结",[1958,2062,2063,2076],{},[1961,2064,2065],{},[1964,2066,2067,2070,2073],{},[1967,2068,2069],{},"构件",[1967,2071,2072],{},"核心作用",[1967,2074,2075],{},"典型装饰器\u002F接口",[1974,2077,2078,2104,2117,2130,2142,2158,2172,2187,2199],{},[1964,2079,2080,2083,2086],{},[1979,2081,2082],{},"控制器",[1979,2084,2085],{},"路由处理、请求参数获取",[1979,2087,2088,2091,2092,2091,2095,2091,2098,2091,2101],{},[145,2089,2090],{},"@Controller",", ",[145,2093,2094],{},"@Get",[145,2096,2097],{},"@Post",[145,2099,2100],{},"@Body",[145,2102,2103],{},"@Param",[1964,2105,2106,2109,2112],{},[1979,2107,2108],{},"提供者",[1979,2110,2111],{},"业务逻辑、依赖注入",[1979,2113,2114],{},[145,2115,2116],{},"@Injectable",[1964,2118,2119,2122,2125],{},[1979,2120,2121],{},"模块",[1979,2123,2124],{},"组织代码结构",[1979,2126,2127],{},[145,2128,2129],{},"@Module",[1964,2131,2132,2135,2138],{},[1979,2133,2134],{},"中间件",[1979,2136,2137],{},"请求前置拦截",[1979,2139,2140],{},[145,2141,704],{},[1964,2143,2144,2147,2150],{},[1979,2145,2146],{},"异常过滤器",[1979,2148,2149],{},"统一错误响应",[1979,2151,2152,2091,2155],{},[145,2153,2154],{},"@Catch",[145,2156,2157],{},"ExceptionFilter",[1964,2159,2160,2163,2166],{},[1979,2161,2162],{},"管道",[1979,2164,2165],{},"数据验证\u002F转换",[1979,2167,2168,2091,2170],{},[145,2169,1173],{},[145,2171,1159],{},[1964,2173,2174,2177,2180],{},[1979,2175,2176],{},"守卫",[1979,2178,2179],{},"鉴权\u002F授权",[1979,2181,2182,2091,2184],{},[145,2183,1376],{},[145,2185,2186],{},"@UseGuards",[1964,2188,2189,2192,2195],{},[1979,2190,2191],{},"拦截器",[1979,2193,2194],{},"请求前后处理、响应映射",[1979,2196,2197],{},[145,2198,1542],{},[1964,2200,2201,2204,2207],{},[1979,2202,2203],{},"自定义装饰器",[1979,2205,2206],{},"参数\u002F方法装饰器复用",[1979,2208,2209],{},[145,2210,1782],{},[23,2212,2213],{},"NestJS 通过这些统一且强有力的抽象，使后端代码结构清晰、易于测试与维护。",[2215,2216,2217],"h2",{"id":2217},"参考文献",[23,2219,2220],{},"以下链接在编写时均可正常访问：",[1958,2222,2223,2233],{},[1961,2224,2225],{},[1964,2226,2227,2230],{},[1967,2228,2229],{},"资料",[1967,2231,2232],{},"说明",[1974,2234,2235,2246,2258],{},[1964,2236,2237,2243],{},[1979,2238,2239],{},[26,2240,2242],{"href":28,"rel":2241},[30],"NestJS 文档",[1979,2244,2245],{},"官方",[1964,2247,2248,2255],{},[1979,2249,2250],{},[26,2251,2254],{"href":2252,"rel":2253},"https:\u002F\u002Fdocs.nestjs.com\u002Ffirst-steps",[30],"NestJS 概览",[1979,2256,2257],{},"第一个应用",[1964,2259,2260,2266],{},[1979,2261,2262],{},[26,2263,2265],{"href":52,"rel":2264},[30],"Fastify 适配器",[1979,2267,2268],{},"性能选项",[2270,2271,2272],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":175,"searchDepth":233,"depth":233,"links":2274},[2275,2276,2277,2278,2280,2281],{"id":68,"depth":240,"text":69},{"id":94,"depth":240,"text":95},{"id":123,"depth":240,"text":124},{"id":1949,"depth":240,"text":2279},"四、CLI 工具 @nestjs\u002Fcli",{"id":2059,"depth":240,"text":2060},{"id":2217,"depth":233,"text":2217},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fbase","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fbase.md","md",{"items":2287},[2288,2292,2296,2300,2304,2308],{"path":2289,"title":2290,"description":2291,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":2293,"title":2294,"description":2295,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。",{"path":2297,"title":2298,"description":2299,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。",{"path":2301,"title":2302,"description":2303,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":2305,"title":2306,"description":2307,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":2309,"title":2310,"description":2311,"category":10,"score":292},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"series":2313,"title":2314,"items":2315,"index":182,"prev":2375,"next":2376},"booklet\u002Fend\u002Fnestjs\u002Fnew","new",[2316,2318,2319,2321,2323,2327,2331,2334,2336,2340,2344,2346,2350,2354,2358,2362,2365,2369,2371],{"path":2289,"title":2290,"date":2317,"pinned":14},"2025-12-23",{"path":7,"title":8,"date":13,"pinned":14},{"path":2293,"title":2294,"date":2320,"pinned":14},"2025-07-04",{"path":2305,"title":2306,"date":2322,"pinned":14},"2023-08-26",{"path":2324,"title":2325,"date":2326,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":2328,"title":2329,"date":2330,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","2023-04-12",{"path":2332,"title":2203,"date":2333,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","2021-09-19",{"path":2309,"title":2310,"date":2335,"pinned":14},"2023-05-26",{"path":2337,"title":2338,"date":2339,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":2341,"title":2342,"date":2343,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":2301,"title":2302,"date":2345,"pinned":14},"2023-09-09",{"path":2347,"title":2348,"date":2349,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":2351,"title":2352,"date":2353,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":2355,"title":2356,"date":2357,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":2359,"title":2360,"date":2361,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","2022-06-15",{"path":2363,"title":2364,"date":2326,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":2366,"title":2367,"date":2368,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":2297,"title":2298,"date":2370,"pinned":14},"2024-12-02",{"path":2372,"title":2373,"date":2374,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":2289,"title":2290,"date":2317,"pinned":14},{"path":2293,"title":2294,"date":2320,"pinned":14}]