အသုံးပြုပုံ
Controller class တစ်ခုလုံး (route အားလုံး) သို့မဟုတ် method တစ်ခုတည်းတွင် decorate လုပ်ရပါသည်။ Middleware များကို အလုပ်လုပ်စေလိုသော အစဉ်အတိုင်း စီရပါသည် — admin API များတွင် auth ကို permission မတိုင်မီ အရင် တပ်လေ့ရှိပါသည်။ App တစ်ခုလုံး၏ request တိုင်းတွင် လိုအပ်ပါက root @Module ၏ globalFilter ကို အသုံးပြုရပါသည်။
1import {
2 AuditLogMiddleware,
3 AuthenticatedUserOnly,
4 CheckAPIPermission,
5 Controller,
6 Get,
7 ResponseDto,
8} from "@quan-erp/shared-backend-core";
9
10@Controller("/admin-dashboard")
11export class AdminDashboardController {
12 @Get("/stats")
13 @AuthenticatedUserOnly()
14 @CheckAPIPermission()
15 @AuditLogMiddleware((req) => `View stats`)
16 async getStats() {
17 return ResponseDto.ok(data);
18 }
19}Builtin middleware
- @AuthenticatedUserOnly() — အကောင့်မဝင်သော caller ကို 401 ဖြင့် ငြင်းပယ်ပါသည် — login လိုအပ်သော endpoint တိုင်းတွင် အသုံးပြုရပါသည်
- @CheckAPIPermission() — လက်ရှိ method နှင့် URL အတွက် အသုံးပြုသူ၏ အခန်းကဏ္ဍ ခွင့်ပြု API ကို စစ်ဆေးပါသည် — admin route တွင် @AuthenticatedUserOnly နှင့် တွဲသုံးရပါသည်
- @AuditLogMiddleware(action) — static string သို့မဟုတ် (req) => string ဖြင့် ထိခိုက်လွယ်သော လုပ်ဆောင်ချက်များ၏ audit မှတ်တမ်း ရေးပါသည်
1import {
2 AuditLogMiddleware,
3 Controller,
4 Get,
5 Put,
6} from "@quan-erp/shared-backend-core";
7
8@Controller("/branch")
9export class BranchController {
10 @AuditLogMiddleware("View all branches")
11 @Get("/")
12 async getAll() { /* … */ }
13
14 @AuditLogMiddleware((req) => `Update branch ${req.params.id}`)
15 @Put("/:id")
16 async update() { /* … */ }
17}Global middleware (module)
Root @Module တွင် filter များကို မှတ်ပုံတင်ပါက controller တစ်ခုတည်းမဟုတ်ဘဲ request တိုင်းတွင် အလုပ်လုပ်ပါသည်။ Request အတွက် globalFilter၊ အမှားကိုင်တွယ်ရန် globalExceptionsFilter ကို အသုံးပြုရပါသည်။ Plugin ကို uninstall လုပ်သောအခါ core က ၎င်းတို့ကို အလိုအလျောက် ဖြုတ်ပေးပါသည်။
- globalFilter: { position, handler }[] — app တစ်ခုလုံးအတွက် request middleware
- globalExceptionsFilter: handler[] — app တစ်ခုလုံးအတွက် exception middleware (IExceptionMiddleware)
- MiddlewarePosition.BEFORE_ROOT_ROUTE — plugin root route မတိုင်မီ အလုပ်လုပ်ပါသည် (auth / resolve-user / logging အတွက် သင့်တော်ပါသည်)
- MiddlewarePosition.AFTER_ROOT_ROUTE — root stack ပြီးနောက် အလုပ်လုပ်ပါသည်
- Handler — Express RequestHandler သို့မဟုတ် IExpressMiddleware / IExceptionMiddleware ကို implement လုပ်သော class
- Class middleware တိုင်းတွင် @MiddlewareMetadata({ plugin: metadata.name }) မဖြစ်မနေ လိုအပ်ပါသည်
1import {
2 MiddlewareMetadata,
3 MiddlewarePosition,
4 Module,
5} from "@quan-erp/shared-backend-core";
6import type {
7 IExceptionMiddleware,
8 IExpressMiddleware,
9} from "@quan-erp/shared-backend-core";
10import type { NextFunction, Request, Response } from "express";
11import metadata from "../../module.metadata.json" with { type: "json" };
12import { MyController } from "./my.controller.js";
13import { MyService } from "./my.service.js";
14
15@MiddlewareMetadata({ plugin: metadata.name })
16export class RequestIdMiddleware implements IExpressMiddleware {
17 handler(req: Request, res: Response, next: NextFunction) {
18 res.setHeader("x-request-plugin", metadata.name);
19 return next();
20 }
21}
22
23@MiddlewareMetadata({ plugin: metadata.name })
24export class PluginErrorFilter implements IExceptionMiddleware {
25 handler(error: Error, req: Request, res: Response, next: NextFunction) {
26 if (res.headersSent) return next(error);
27 res.status(500).json({ message: error.message });
28 }
29}
30
31@Module({
32 name: metadata.name,
33 providers: [MyService],
34 controllers: [MyController],
35 entities: [],
36 globalFilter: [
37 {
38 position: MiddlewarePosition.BEFORE_ROOT_ROUTE,
39 handler: RequestIdMiddleware,
40 },
41 ],
42 globalExceptionsFilter: [PluginErrorFilter],
43})
44export class MyPluginModule {}ကိုယ်ပိုင် middleware ဖန်တီးခြင်း
Controller သို့မဟုတ် method အတွက် Middleware(...) ကို decorator အဖြစ် ထုပ်ပိုးရေးရပါသည်။ DI သိသော handler သို့မဟုတ် globalFilter အတွက် IExpressMiddleware / IExceptionMiddleware ကို implement လုပ်နိုင်ပါသည်။ Class middleware တိုင်းတွင် @MiddlewareMetadata({ plugin: metadata.name }) မဖြစ်မနေ ကြေညာရပါသည် — core က မှန်ကန်သော plugin DI scope တွင် resolve လုပ်ရန်ဖြစ်ပါသည်။ Route ပေါ်တွင် @MyDecorator() သို့မဟုတ် @Middleware(MyClass) ဖြင့် တပ်ဆင်ရပါသည်။
- လိုအပ်ပါသည် — IExpressMiddleware / IExceptionMiddleware class တိုင်းတွင် @MiddlewareMetadata({ plugin: metadata.name })
- Decorator ပုံစံ — factory မှ Middleware(async (req, res, next) => { … }) ပြန်ပေးရပါသည် (function handler ဖြစ်၍ MiddlewareMetadata မလိုအပ်ပါ)
- Class ပုံစံ (IExpressMiddleware) — handler(req, res, next); @Inject သည် @Service() မလိုဘဲ အလုပ်လုပ်ပါသည်
- Exception middleware (IExceptionMiddleware) — handler(error, req, res, next)
- Middleware ကို တစ်ခုတည်းသော တာဝန်အပေါ် အာရုံစိုက်ထားရပါသည် — လုပ်ငန်းစည်းမျဉ်းများကို ဖြစ်နိုင်လျှင် service တွင် ထားရှိရပါသည်
1import {
2 HttpStatus,
3 Middleware,
4 ResponseDto,
5} from "@quan-erp/shared-backend-core";
6
7export function MyCustomAuth(): MethodDecorator & ClassDecorator {
8 return Middleware(async (req, res, next) => {
9 if (req.headers["x-custom-header"] === "secret-value") return next();
10 return res
11 .status(HttpStatus.UNAUTHORIZED)
12 .json(ResponseDto.error("Unauthorized", HttpStatus.UNAUTHORIZED));
13 });
14}1import type { NextFunction, Request, Response } from "express";
2import {
3 Controller,
4 Inject,
5 Middleware,
6 MiddlewareMetadata,
7} from "@quan-erp/shared-backend-core";
8import type { IExpressMiddleware } from "@quan-erp/shared-backend-core";
9import metadata from "../../module.metadata.json" with { type: "json" };
10import { MyService } from "./my.service.js";
11
12@MiddlewareMetadata({ plugin: metadata.name })
13export class MyComplexMiddleware implements IExpressMiddleware {
14 @Inject(MyService)
15 private myService: MyService;
16
17 async handler(req: Request, res: Response, next: NextFunction) {
18 if (await this.myService.validate(req.body)) return next();
19 res.status(400).send("Invalid request");
20 }
21}
22
23@Middleware(MyComplexMiddleware)
24@Controller("/complex")
25export class ComplexController {}