Tải bản đầy đủ (.pdf) (190 trang)

v4 0 nest js basic docs thuc tap tot nghiep

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.56 MB, 190 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

about:blank 1/190

TÀILIỆUKHĨAHỌC“Nest.JSvớiTypeScript/MongoDBSiêuDễ”

- Thêmtómtắtchocácchươngtàiliệu.

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

Giới thiệu về khóa học và tác giả, cũng như demo kết quả đạt được sau khi kết thúc khóahọc này.

- Hiểurõ,thựchànhvàápdụngđượcngơnngữTypescriptchodựánNestJS- XâydựngtưduyBackendvớitính“mởrộng”cao,bằngcáchhọc&sửdụng

- Thựchànhdựánviếtbackendchowebsitecloneitviec.com(websiteđăngtin/ứngtuyểnviệclàm)

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

about:blank 7/190#0.2.uCầuCủaKhóaHọc

- CầncósựhiểubiếtcơbảnvềTypescript.Nếubạnchưabiết,cóthểhọcnhanhtạiđây:

- CầncókiếnthứcvềMongoDB(sửdụngvớiMongoose).Nếuchưabiết,bạncóthểthamkhảokhóahọcnày:

- CàiđặtmơitrườngNode.JS:trongkhóahọcnày,máytínhcủamìnhdùngversionNode.JS16.20.0

- CàiđặtGit:cácthaotácvớiGitvàsửdụngGithub,mìnhkhơnghướngdẫn.BạnnàochưabiếtdùngGit,xemtạiđây:

- CàiđặtVisualStudioCode:đâylàcơngcụdùngđểcode

6

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

VớicácbạnhọcviênUdemy,đểđảmbảoquyềnlợi,cácbạnchủđộnginboxquafanpageHỏiDânITđểnhậnđượcsựhỗtrợtrongqtrìnhhọctậpnhé: class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

about:blank 9/1904.Vềchuyệnleakkhóahọcvàmualậu

VỚICÁCBẠNMUALẬU,MÌNHCHỈMUỐNCHIASẺTHẾNÀY:1. TRÊNĐỜINÀY,CHẲNGCĨGÌCHẤTLƯỢNGMÀMIỄNPHÍCẢ.

2. HÃYHỌCTHĨIQUENTRÂNTRỌNGGIÁTRỊLAOĐỘNG

NĨLÀTHĨIQUEN,CŨNGNHƯSẼLÀMỘTPHẦNTÍNHCÁCHCỦABẠN.ĐỪNGVÌNGHÈOQMÀLÀMMẤTĐITÍNHCÁCHCỦABẢNTHÂN.NẾUKHĨKHĂN,CỨINBOXMÌNH,MÌNHHỖTRỢ.VIỆCGÌPHẢILÀMVẬY=))3. MÌNHĐÃTỪNGLÀSINHVIÊNGIỐNGBẠN,MÌNHHIỂUTẠISAOCÁCBẠNLÀM

VẬY. HÃYBIẾTCHOĐI.SỐNGÍCHKỶ,THÌTHEOLUẬTNHÂNQUẢĐẤY,CHẲNGCĨGÌLÀNGẪUNHIÊNCẢ

4. NẾUBẠNTHẤYKHĨAHỌCHAY,HÃYBIẾTDONATEĐỂỦNGHỘTÁCGIẢ.LINKDONATE: class="text_page_counter">Trang 10</span><div class="page_container" data-page="10">

Youtube“HỏiDânIT”: class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

about:blank 11/190Chapter1:TổngquanvềNest.JS

Giới thiệu tổng quan về Framework Nest.js và trả lời câu hỏi, tại sao chúng ta lại cầnNest.JS, từ đấy viết chương trình Hello World với Framework này.

+ OOP(ObjectOrientedProgramming-lậptrìnhhướngđốitượng)

+ FP(FunctionalProgramming),tươngtựnhưfunctioncomponent(khidùngvớiReact.js)

+ FRP(FunctionalReactiveProgramming)(tươngtựrxjscủaangular)

10

</div><span class="text_page_counter">Trang 12</span><div class="page_container" data-page="12">

Nest.jssẽcungcấpbộkhungframework(architecture-kiếntrúc),việccủachúngtalàsửdụngbộkhungđấyđểbuildsảnphẩmmìnhmuốn.

</div><span class="text_page_counter">Trang 13</span><div class="page_container" data-page="13">

about:blank 13/190#2.CreateANewProject

Lư:mơitrườngcàiđặtNode.js16.xgulp'CàiđặtNestCLI: npmi-g@nestjs/

12

</div><span class="text_page_counter">Trang 14</span><div class="page_container" data-page="14">

+ filemain.tslàfilechính.ứngdụngNest.jssẽchạyfilenàyđầutiên(tươngtựfileserver.jstrongkhóahọcrestfulapi)

</div><span class="text_page_counter">Trang 15</span><div class="page_container" data-page="15">

about:blank 15/190-Cácfilephụ:

14

</div><span class="text_page_counter">Trang 16</span><div class="page_container" data-page="16">

- Cầnchiatheomodule,đểcóthểpháttriểnđộclập,đồngthời,tínhnăngnàysẽítảnhhưởngtớitínhnăngkia(on/offthemuốn)

-- Filemain.tssẽchạyappmodules,vàappmodulessẽbaogồmtấtcảcácmodulescon.

Vídụ:đểkếtnốitớidatabase,UsersModulescóthểbaogồmDatabaseModules

</div><span class="text_page_counter">Trang 17</span><div class="page_container" data-page="17">

about:blank 17/190Chapter2:NestJSvàTypescript

Tìm hiểu và học cách sử dụng Decorator của Typescript vào Nest.JS, từ đấy nắm vữngcách hoạt động Router và Controller khi sử dụng các Decorator có sẵn do Nest.JS cungcấp.

16

</div><span class="text_page_counter">Trang 18</span><div class="page_container" data-page="18">

}

</div><span class="text_page_counter">Trang 19</span><div class="page_container" data-page="19">

about:blank 19/190#6.SửdụngDecoratorvớiNest.JS

18

</div><span class="text_page_counter">Trang 20</span><div class="page_container" data-page="20">

classExampleClass{@decorate1( )@decorate2method(){

tạisaolạisửdụng:@decorate1() =>cầndấu()và @decorate2=>khơngcần()=>phụthuộcvàocáchviếtdecorator

Vídụ:@Controller(),@Injectable()...

</div><span class="text_page_counter">Trang 21</span><div class="page_container" data-page="21">

about:blank 21/190#7.MơhìnhRoutervớiNest.JS

20

</div><span class="text_page_counter">Trang 22</span><div class="page_container" data-page="22">

}

</div><span class="text_page_counter">Trang 23</span><div class="page_container" data-page="23">

about:blank 23/1902.CáchxửlýcủaNest.JS

@Controller()//khơngcóthamsố@Get('/order') //GET/order

@Controller('order)@Get() //GET/order

22

</div><span class="text_page_counter">Trang 24</span><div class="page_container" data-page="24">

@Get() nếubạnkhôngtruyênthamsố=>sinhraGET"/"@Get("/path") nếubạntruyênthamsố=>sinhraGET"/path"

@Get('/user) =>sinhraroute"/user"

@Get('/filter-by-name) =>sinhraroute"/user1/filter-by-name"

</div><span class="text_page_counter">Trang 25</span><div class="page_container" data-page="25">

about:blank 25/190Chapter3: InversionOfControl

Khi Học về OOP (lập trình hướng đối tượng), một trong các cách dùng để tối ưu hóa ứngdụng là áp dụng mơ hình IoC(Inversion of control) và DI (Dependency injection). Chươngnày sẽ giúp chúng ta học cách sử dụng các “design pattern” trên vào framework Nest.JSLưuý:

24

</div><span class="text_page_counter">Trang 26</span><div class="page_container" data-page="26">

}

</div><span class="text_page_counter">Trang 27</span><div class="page_container" data-page="27">

about:blank 27/190publicclassB{

26

</div><span class="text_page_counter">Trang 28</span><div class="page_container" data-page="28">

Minhhọa=hìnhcáicây(tree).Cácmoduleschínhlàcáclácủa1cáicây.Lánàyrụngsẽkhơnglàmảnhhưởngtớicây,haycáclácịnlại.

</div><span class="text_page_counter">Trang 29</span><div class="page_container" data-page="29">

about:blank 29/190Ứngdụngtrongthựctế:

28

</div><span class="text_page_counter">Trang 30</span><div class="page_container" data-page="30">

cịn1thànhphần,gọilàinjector(giúptạoraDI,vàlàmchoclassAvàBkhơngphụthuộcvàonhau:v)

</div><span class="text_page_counter">Trang 31</span><div class="page_container" data-page="31">

about:blank 31/1902.Vídụvềphạmvi(scope)vàcáchsửdụngDI

30

</div><span class="text_page_counter">Trang 32</span><div class="page_container" data-page="32">

}

</div><span class="text_page_counter">Trang 33</span><div class="page_container" data-page="33">

about:blank 33/190Chapter4:NestJSvàMVC

NestJS cũng có đủ khả năng và sức mạnh để làm Server theo mơ hình MVC truyền thống.Tại đây, chúng ta sẽ tìm hiểu về View Engine, cách viết code theo mơ hình

Model-View-Controller và các nhược điểm đang cịn tồn đọng của mơ hình này.#12.Vídụvềcontroller/service

32

</div><span class="text_page_counter">Trang 34</span><div class="page_container" data-page="34">

#14.MơhìnhMVC-KhơngcóModel?

</div><span class="text_page_counter">Trang 35</span><div class="page_container" data-page="35">

about:blank 35/190#15.VấnĐềtồnđọngvớiSSR?

34

</div><span class="text_page_counter">Trang 37</span><div class="page_container" data-page="37">

about:blank 37/190Chapter5:ConnectDatabase

Trong chương này, chúng ta sẽ cùng nhau kết nối backend tới Database bằng cách sửdụng MongoDB. Ngồi ra, sẽ tối ưu hóa cách sử dụng “hằng số”, dựa vào cách sử dụngtham số môi trường (.env) với Nest.JS Config.

36

</div><span class="text_page_counter">Trang 38</span><div class="page_container" data-page="38">

CàiđặtMongoDBServerhoặctạotàikhoảnvàsửdụngdatabaseAtlasonline

</div><span class="text_page_counter">Trang 39</span><div class="page_container" data-page="39">

about:blank 39/190#18.SửdụngMongoDBvớiNestJS

38

</div><span class="text_page_counter">Trang 40</span><div class="page_container" data-page="40">

- Nhiềuhơn1file.env,vídụmỗimơitrườngsửdụnglà1file.envMơitrườngtest:.env.test

- Chúngtamuốnvalidatedữliệucủabiếntrong.env.Cáchlàmtruyềnthống,sửdụngtrựctiếp.envlàkhơnglàmđược

Vềbảnchất,ConfigServicecũngsửdụngthưviện.env,tuynhiên,nóđã“codethêm”đểgiảiquyết2vấnđềchúngtanêuởtrên(sửdụngnhiềufile.envvàvalidatefile.env)

</div><span class="text_page_counter">Trang 41</span><div class="page_container" data-page="41">

about:blank 41/1903.SửdụngConfigService

Tàiliệu: Khaibáoconfigserviceởconstructor(dùngdependencyinjection)

constructor(privateconfigService:ConfigService){}- Lấygiátrịcủa.env,theocúpháp:

40

</div><span class="text_page_counter">Trang 42</span><div class="page_container" data-page="42">

Ngoài khả năng có thể tạo server theo mơ hình MVC, Nest.JS cũng có thể làm serverRestful APIs. Chúng ta sẽ cùng nhau viết nhanh module Users theo đúng chuẩn Restful,sử dụng các cơng cụ có sẵn của Nest.JS, bao gồm generate resources, schema,controller và services.

class="text_page_counter">Trang 43</span><div class="page_container" data-page="43">

about:blank 43/190#21.CreateSchema(Model)

TạoUserModelvớicácthuộctính:- Email

- Password- Name- Address- Phone- Age

42

</div><span class="text_page_counter">Trang 44</span><div class="page_container" data-page="44">

EmailPasswordNameAddressPhoneAge}

</div><span class="text_page_counter">Trang 45</span><div class="page_container" data-page="45">

about:blank 45/190#22.2HashUser’sPassword

44

</div><span class="text_page_counter">Trang 46</span><div class="page_container" data-page="46">

- Transformdata:convertstring=>number,array…- Validatedata

@@0.5.1Vềclass-validator: class="text_page_counter">Trang 47</span><div class="page_container" data-page="47">

about:blank 47/190#23.GetUserbyId

46

</div><span class="text_page_counter">Trang 48</span><div class="page_container" data-page="48">

DELETEhttp://localhost:8000/users/:idBody:Khôngcầntruyền,màtruyềnidởurl

</div><span class="text_page_counter">Trang 49</span><div class="page_container" data-page="49">

about:blank 49/190Chapter7:StatefulvàStateless

Mọi website đều hoạt động dựa trên mơ hình Stateful và Stateless. Ở đây, chúng ta cầnnắm vững, hiểu rõ và có khả năng phân biệt điểm khác nhau của 2 mơ hình này, bởi vì,việc chúng ta lựa chọn mơ hình nào, nó sẽ quyết định cách thức tổ chức code cho dự áncủa chúng ta.

Saukhikéocodevề,chạycáccâulệnhsau:(versionmìnhsửdụnglànode16.x)npmi =>càiđặtthưviện

setup urlMongodb,file.env

-vớistateful:sửdụngroute/login /uservàroute'/'-vớistateless:sửdụngendpoint

+login: /stateless/login =>truyềnbodygồmusernamevàpassword+getusers /stateless/user =>cầntruyềnbearertokenởheaderrequest

48

</div><span class="text_page_counter">Trang 50</span><div class="page_container" data-page="50">

Mặcđịnh,nestjshỗtrợcâulệnhdebugsđểđặtbreakpoint: start:debug:"neststart--debug--watch",

]

</div><span class="text_page_counter">Trang 51</span><div class="page_container" data-page="51">

about:blank 51/1903.Sửdụngdebugs

50

</div><span class="text_page_counter">Trang 52</span><div class="page_container" data-page="52">

#28.StatefulApplicationWhoyouare? user/guest

2.CácphươngpháplưutrữthôngtincủaclientvàserverClient(browser):localstorage,session,cookiesServer:session(memory/RAM,diskstorage/file,database)

</div><span class="text_page_counter">Trang 53</span><div class="page_container" data-page="53">

about:blank 53/190#29.Cơchếhoạtđộngcủastatefulapp

52

</div><span class="text_page_counter">Trang 54</span><div class="page_container" data-page="54">

Vídụ:khibạnthựchiệnchuyểnkhoảnliênngânhàng.từvcb=>mb,sửdụngứngdụngcủavcb.nhưvậy,khibạnchuyểnkhoảntớimb,mbkobiếtbạnlàai,cóhợplệhaykhơng...

</div><span class="text_page_counter">Trang 55</span><div class="page_container" data-page="55">

about:blank 55/190#31.Mơhìnhstateless

54

</div><span class="text_page_counter">Trang 56</span><div class="page_container" data-page="56">

khơngcócáchnàođểcóthểdeletetokenđấy.Cónghĩalà,nếutokenđanghợplệ,bạnkhơngthểdeletetokenđấy

</div><span class="text_page_counter">Trang 57</span><div class="page_container" data-page="57">

about:blank 57/190Chapter8:JWT-JsonWebToken

Sử dụng mơ hình Stateless, server sẽ khơng có “session” để kiểm tra user có hợp lệ haykhông, nên JWT (Json web token) là một giải pháp rất phổ biến được dùng cho mơ hìnhnày. Ở đây, chúng ta sẽ tìm hiểu về JWT, cũng như áp dụng nó để xác thực người dùngtrong dự án Nest.JS

56

</div><span class="text_page_counter">Trang 58</span><div class="page_container" data-page="58">

- localStorage:access_token->thuậntiệnviệctruycập/lưutrữtoken.lấydatatừlocalStorage:localStorage.get('item').

client(javascript):khôngthểlấycookies=hàm document.cookie

</div><span class="text_page_counter">Trang 59</span><div class="page_container" data-page="59">

about:blank 59/190Cookiessẽtựhếthạntheo1thờigiannhấtđịnh(nếusetexpireddate)=>kodùngnó

58

</div><span class="text_page_counter">Trang 60</span><div class="page_container" data-page="60">

passport-local:xácthựcngườidùngthơngquausername/passwordpassport-jwt:xácthựcngườidùngvớijwt(jsonwebtoken)

</div><span class="text_page_counter">Trang 61</span><div class="page_container" data-page="61">

about:blank 61/190#36.LocalStrategiesvớiNestJS

- passportlàthưviệngốc=>giúpratạoramiddleware(canthiệpvàreqvàres),vàlưutrữthơngtinngườidùngđăngnhập(req.user)

- @nestjs/passportlàthưviệnviếttheophongcáchcủanestjs,giúpviệccanthiệpvàopassportdễdànghơn

- passport-local:đâylàstrategyhỗtrợviệcđăngnhậpsửdụngusername/passwordSaunày,khicầntạorajwt,chúngtasẽcàithêmstrategy:passport-jwt

60

</div><span class="text_page_counter">Trang 62</span><div class="page_container" data-page="62">

providers: theprovidersthatwillbeinstantiatedbytheNestinjectorandthatmaybesharedatleastacrossthismodule

Imports: thelistofimportedmodulesthatexporttheproviderswhicharerequiredinthismodule

Chúngtacầnxuấtra(xuấtservices/providers)thìcáiimportởtrênmớicótácdụng

</div><span class="text_page_counter">Trang 63</span><div class="page_container" data-page="63">

about:blank 63/190#37.NestjsGuard

- req->route->middleware.dữliệukohợplệ,khơngthựcthitiếp->res(thơngbáolỗi)- req->route->middleware.dữliệuhợplệ=>next()->controller->service->resHiểuđơngiản,middleware,nhưtêngọicủanó.giúpbạncanthiệpvàogiữareqvàres:req->middleware->res

62

</div><span class="text_page_counter">Trang 64</span><div class="page_container" data-page="64">

3.VídụvềviếtvàsửdụngGuardđơngiản

</div><span class="text_page_counter">Trang 65</span><div class="page_container" data-page="65">

about:blank 65/190#38.LocalGuardvớiPassport

64

</div><span class="text_page_counter">Trang 66</span><div class="page_container" data-page="66">

class="text_page_counter">Trang 67</span><div class="page_container" data-page="67">

about:blank 67/190#41.Enableauthenticationglobally

66

</div><span class="text_page_counter">Trang 68</span><div class="page_container" data-page="68">

class="text_page_counter">Trang 69</span><div class="page_container" data-page="69">

about:blank 69/190#43.Fixbugsvàtổngkết

68

</div><span class="text_page_counter">Trang 70</span><div class="page_container" data-page="70">

LuồngprotectedroutesvớiJWT(cầntruyềnlênJWTởheaderrequest)

</div><span class="text_page_counter">Trang 71</span><div class="page_container" data-page="71">

about:blank 71/190Chapter9:Tưduyphântíchdatabase

Giới thiệu đề tài dự án thực hành cuối khóa, cũng như tư duy phân tích database, cáchthiết kế table và mối quan hệ giữa các đối tượng trong dự án thực hành.

70

</div><span class="text_page_counter">Trang 72</span><div class="page_container" data-page="72">

Actors:(ngườisửdụnghệthống)- Ứngviên(employee)- Nhàtuyểndụng:company- admin

đốitượngkhác:- CVcủaứngviên- jobsđăngtuyển- Skillsđểsearch

- role:vaitrịcủausertronghệthống(admin,hr...)

- permission:quyềnhạnsửdụnghệthống-ámchỉapicủabackend

1nhàtuyểndụngcóthểđăngnhiềujobs1jobchỉthuộc1nhàtuyểndụng1skillscóthểthuộcnhiềujobs1jobscóthểcónhiềuskills

</div><span class="text_page_counter">Trang 73</span><div class="page_container" data-page="73">

about:blank 73/190Vềphânquyền:

72

</div><span class="text_page_counter">Trang 74</span><div class="page_container" data-page="74">

status:string //PENDING-REVIEWING-APPROVED-REJECTED

</div><span class="text_page_counter">Trang 75</span><div class="page_container" data-page="75">

about:blank 75/190history:arrayobject[{status:string,updatedAt:Date,updatedBy:{_id,email}}]

74

</div><span class="text_page_counter">Trang 76</span><div class="page_container" data-page="76">

-name:string-path:string-method:string-description:string-createdAt:Date-updatedAt:Date-isDeleted:boolean-createdBy:object{_id,email}-updatedBy:object{_id,email}-deleteBy:object{_id,email}

</div><span class="text_page_counter">Trang 77</span><div class="page_container" data-page="77">

about:blank 77/190Chapter10:MongoosePlugins

Để có thể sử dụng Mongoose (MongoDB) hiệu quả, chúng ta sẽ cùng nhau cài đặt cácplugin hỗ trợ việc Query/Filter kết quả, thực hiện “soft-delete”, tự động tạo “timestamp” vàđặc biệt, khắc phục lỗi CORS với Nest.JS

76

</div><span class="text_page_counter">Trang 78</span><div class="page_container" data-page="78">

deletedAt:null,isDeleted:false

</div><span class="text_page_counter">Trang 79</span><div class="page_container" data-page="79">

about:blank 79/190#49.QueryBuilder

78

</div><span class="text_page_counter">Trang 80</span><div class="page_container" data-page="80">

Lưuý:checkoutcodetheotừngmodulesđểthựchànhsongsongvớibackend

</div><span class="text_page_counter">Trang 81</span><div class="page_container" data-page="81">

about:blank 81/190#51.CORSlàgì?

+ domain:tênwebsitesửdụngcookiesnày+ value:giátrịcủacookies

80

</div><span class="text_page_counter">Trang 82</span><div class="page_container" data-page="82">

Thựctế:dofacebook.comvàhacker.comlà2domainkhácnhau,nênsẽbịchặnCORSdefault:v

</div><span class="text_page_counter">Trang 83</span><div class="page_container" data-page="83">

about:blank 83/190#52.1LàmsaođểbypassCORS?

- Backenddobạnkiểmsốt,lỗixảyrakhifrontendgọilênbackend=>fixởbackend(cáchlàmnàysẽđượchướngdẫnởvideotiếptheo)

- Backenddobênthứ3làm.

Mơhình:frontend=> backend(củabạn)=>backend(củađốitác)Bạncóbiếtrằng,thưviệnaxios,dùngđượccảfrontendlẫnbackend:v

82

</div><span class="text_page_counter">Trang 84</span><div class="page_container" data-page="84">

"optionsSuccessStatus":204}

</div><span class="text_page_counter">Trang 85</span><div class="page_container" data-page="85">

about:blank 85/190Chapter11:ModulesCompany

Bài tập thực hành: tạo module “Company”. Ngoài việc thực hiện CRUD, chúng ta sẽ tìmhiểu cách phân trang (paginate data), sử dụng Interceptor để xử lý data trước khi trả vềclient, customize message response cũng như “đánh version” cho API

84

</div><span class="text_page_counter">Trang 86</span><div class="page_container" data-page="86">

Body{name,address,description}Cóvalidatedữliệukhitạomới

</div><span class="text_page_counter">Trang 87</span><div class="page_container" data-page="87">

about:blank 87/190#55.UpdateUserType(JWT)

86

</div><span class="text_page_counter">Trang 88</span><div class="page_container" data-page="88">

5.Move/login=>authcontroller

</div><span class="text_page_counter">Trang 89</span><div class="page_container" data-page="89">

about:blank 89/190#56.PassingReq.user

88

</div><span class="text_page_counter">Trang 90</span><div class="page_container" data-page="90">

Tạoendpoint:Patch /companies/id(lưuýtruyềntokenJWTởheader)Body{

Cóvalidatedữliệu,vàđồngthờicậpnhậttrườngupdatedBy.

</div><span class="text_page_counter">Trang 91</span><div class="page_container" data-page="91">

about:blank 91/190#58.BàiTậpDeleteCompany

Yêucầu:Tạoendpoint:Delete /companies/id

90

</div><span class="text_page_counter">Trang 92</span><div class="page_container" data-page="92">

pages:totalPages, //tổngsốtrangvớiđiềukiệnquerytotal:totalItems//tổngsốphầntử(sốbảnghi)},

-Counttổngbảnghivớiđiềukiệnfilter-tínhoffset

</div><span class="text_page_counter">Trang 93</span><div class="page_container" data-page="93">

about:blank 93/190@Query/skip/limit

92

</div><span class="text_page_counter">Trang 94</span><div class="page_container" data-page="94">

Observable> <Promise

</div><span class="text_page_counter">Trang 95</span><div class="page_container" data-page="95">

about:blank 95/190#61.1TransformResponse

94

</div><span class="text_page_counter">Trang 97</span><div class="page_container" data-page="97">

about:blank 97/190

</div><span class="text_page_counter">Trang 99</span><div class="page_container" data-page="99">

about:blank 99/190

</div><span class="text_page_counter">Trang 101</span><div class="page_container" data-page="101">

about:blank 101/190

</div><span class="text_page_counter">Trang 103</span><div class="page_container" data-page="103">

about:blank 103/190

</div><span class="text_page_counter">Trang 105</span><div class="page_container" data-page="105">

about:blank 105/190

</div><span class="text_page_counter">Trang 107</span><div class="page_container" data-page="107">

about:blank 107/190

</div><span class="text_page_counter">Trang 109</span><div class="page_container" data-page="109">

about:blank 109/190

</div><span class="text_page_counter">Trang 111</span><div class="page_container" data-page="111">

about:blank 111/190

</div><span class="text_page_counter">Trang 113</span><div class="page_container" data-page="113">

about:blank 113/190

</div><span class="text_page_counter">Trang 115</span><div class="page_container" data-page="115">

about:blank 115/190

</div><span class="text_page_counter">Trang 117</span><div class="page_container" data-page="117">

about:blank 117/190

</div><span class="text_page_counter">Trang 119</span><div class="page_container" data-page="119">

about:blank 119/190

</div><span class="text_page_counter">Trang 121</span><div class="page_container" data-page="121">

about:blank 121/190

</div><span class="text_page_counter">Trang 123</span><div class="page_container" data-page="123">

about:blank 123/190

</div><span class="text_page_counter">Trang 125</span><div class="page_container" data-page="125">

about:blank 125/190

</div><span class="text_page_counter">Trang 127</span><div class="page_container" data-page="127">

about:blank 127/190

</div><span class="text_page_counter">Trang 129</span><div class="page_container" data-page="129">

about:blank 129/190

</div><span class="text_page_counter">Trang 131</span><div class="page_container" data-page="131">

about:blank 131/190

</div><span class="text_page_counter">Trang 133</span><div class="page_container" data-page="133">

about:blank 133/190

</div><span class="text_page_counter">Trang 135</span><div class="page_container" data-page="135">

about:blank 135/190

</div><span class="text_page_counter">Trang 137</span><div class="page_container" data-page="137">

about:blank 137/190

</div><span class="text_page_counter">Trang 139</span><div class="page_container" data-page="139">

about:blank 139/190

</div><span class="text_page_counter">Trang 141</span><div class="page_container" data-page="141">

about:blank 141/190

</div><span class="text_page_counter">Trang 143</span><div class="page_container" data-page="143">

about:blank 143/190

</div><span class="text_page_counter">Trang 145</span><div class="page_container" data-page="145">

about:blank 145/190

</div><span class="text_page_counter">Trang 147</span><div class="page_container" data-page="147">

about:blank 147/190

</div><span class="text_page_counter">Trang 149</span><div class="page_container" data-page="149">

about:blank 149/190

</div><span class="text_page_counter">Trang 151</span><div class="page_container" data-page="151">

about:blank 151/190

</div><span class="text_page_counter">Trang 153</span><div class="page_container" data-page="153">

about:blank 153/190

</div><span class="text_page_counter">Trang 155</span><div class="page_container" data-page="155">

about:blank 155/190

</div><span class="text_page_counter">Trang 157</span><div class="page_container" data-page="157">

about:blank 157/190

</div><span class="text_page_counter">Trang 159</span><div class="page_container" data-page="159">

about:blank 159/190

</div><span class="text_page_counter">Trang 161</span><div class="page_container" data-page="161">

about:blank 161/190

</div><span class="text_page_counter">Trang 163</span><div class="page_container" data-page="163">

about:blank 163/190

</div><span class="text_page_counter">Trang 165</span><div class="page_container" data-page="165">

about:blank 165/190

</div><span class="text_page_counter">Trang 167</span><div class="page_container" data-page="167">

about:blank 167/190

</div><span class="text_page_counter">Trang 169</span><div class="page_container" data-page="169">

about:blank 169/190

</div><span class="text_page_counter">Trang 171</span><div class="page_container" data-page="171">

about:blank 171/190

</div><span class="text_page_counter">Trang 173</span><div class="page_container" data-page="173">

about:blank 173/190

</div><span class="text_page_counter">Trang 175</span><div class="page_container" data-page="175">

about:blank 175/190

</div><span class="text_page_counter">Trang 177</span><div class="page_container" data-page="177">

about:blank 177/190

</div><span class="text_page_counter">Trang 178</span><div class="page_container" data-page="178">

npmi--save@nestjs/

</div><span class="text_page_counter">Trang 179</span><div class="page_container" data-page="179">

about:blank 179/190#109.Swagger

{<small>type 'http'</small>: ,<small>scheme 'Bearer'</small>: ,<small>bearerFormat 'JWT'</small>: ,<small>in 'header'</small>: ,},<small>'token'</small>,)

178

</div><span class="text_page_counter">Trang 180</span><div class="page_container" data-page="180">

-Chưaautoaddtocontroller-ChưahandletypeMongoID

</div><span class="text_page_counter">Trang 181</span><div class="page_container" data-page="181">

about:blank 181/190Codethamkhảophầncấuhìnhswagger:

180

</div><span class="text_page_counter">Trang 182</span><div class="page_container" data-page="182">

3.Devopsprometheusvsgrafana

</div><span class="text_page_counter">Trang 183</span><div class="page_container" data-page="183">

about:blank 183/190#111.DocsWholeAppBackend

182

</div><span class="text_page_counter">Trang 184</span><div class="page_container" data-page="184">

};}

</div><span class="text_page_counter">Trang 185</span><div class="page_container" data-page="185">

about:blank 185/190#113.UpgradeNestJSVersion

Câulệnh:ncu-usẽlàmthayđổipackage.json=>cầnchạycâulệnhnpmi đểcàiđặt

184

</div><span class="text_page_counter">Trang 186</span><div class="page_container" data-page="186">

npmERR! @nestjs/core@"10.0.3"fromtherootprojectnpmERR! node_modules/@nestjs-modules/mailer

npmERR! @nestjs-modules/mailer@"1.8.1"fromtherootprojectnpmERR! 7more(@nestjs/mongoose,@nestjs/platform-express,...)npmERR!

npmERR! peerOptional@nestjs/platform-express@"^10.0.0"from@nestjs/

npmERR! node_modules/@nestjs/core

npmERR! @nestjs/core@"10.0.3"fromtherootprojectnpmERR!

=>sửdụng--legacy-peer-depsnpmi--legacy-peer-deps

</div><span class="text_page_counter">Trang 187</span><div class="page_container" data-page="187">

about:blank 187/190=====

npmi-g@nestjs/ =>trùngversionvớidevDependenciesKiểmtraversioncàiđặtglobal:npmlist-g

186

</div><span class="text_page_counter">Trang 188</span><div class="page_container" data-page="188">

class="text_page_counter">Trang 189</span><div class="page_container" data-page="189">

about:blank 189/190#115.NhậnXétVềKhóaHọc

188

</div><span class="text_page_counter">Trang 190</span><div class="page_container" data-page="190">

Hẹngặplạicácbạnởcáckhóahọctiếptheo….HỏiDânIT(Eric)

</div>

×