Tổng quan về các package Backend
Trang này mô tả kiến trúc backend đầy đủ của hệ thống POS BANA. Nội dung bao gồm tất cả 18 package trong thư mục packages/, cơ sở dữ liệu PostgreSQL dùng chung với 14 schema, hạ tầng event-driven (Kafka domain event + Debezium CDC; Redis cho cache, WebSocket fan-out và BullMQ), các cơ chế bảo mật, và các pattern của framework IGNIS thống nhất toàn bộ codebase.
Stack công nghệ
Phiên bản được single-source - xem Platform Facts → Stack ứng dụng (tự sinh từ overrides trong package.json gốc; lint lúc build chặn drift). Backend dựng trên IGNIS (framework DI) + Hono (HTTP) + Drizzle ORM / Zod (dữ liệu + xác thực) trên runtime Bun.
Cấu trúc hệ thống
Tất cả 18 package Backend
| Package | Port | Vai trò | Trách nhiệm chính | Phụ thuộc chính |
|---|---|---|---|---|
@nx/core | -- | Nền tảng | Base class, DB model trên 14 schema, tiện ích, cấu hình xác thực | -- |
@nx/identity | 31010 | Service | Xác thực, phân quyền, quản lý người dùng, RBAC | core |
@nx/commerce | 31020 | Service | Sản phẩm, engine định giá, merchant, danh mục, CDC | core, asset, inventory, search |
@nx/sale | 31030 | Service | Vòng đời đơn hàng, checkout, đơn bếp, điều phối thanh toán | core, mq-pay |
@nx/inventory | 31050 | Service | Theo dõi tồn kho, đơn mua hàng, quản lý nhà cung cấp | core |
@nx/finance | 31040 | Service | Ví, theo dõi thu/chi, danh mục tài chính | core |
@nx/pricing | 31070 | Service | Bộ giá, engine thuế, khuyến mãi, quy tắc định giá | core |
@nx/payment | 31080 | Service | Cấu hình webhook, tải thông tin xác thực, phân phối thanh toán | core, mq-pay |
@nx/ledger | 31060 | Service | Tạo sổ kế toán HKD (PDF/XLSX), mã hóa, S3 | core |
@nx/outreach | 31110 | Service | Đăng ký nhận tin, biểu mẫu liên hệ | core |
@nx/licensing | 31120 | Service | Quản lý license theo policy, ký chứng chỉ, pipeline xác thực | core |
@nx/helpdesk | 31032 | Service | Hỗ trợ khách hàng đa kênh - ticket, SLA, tự phân công, cơ sở tri thức, khảo sát (build hiện đang lỗi) | core |
@nx/taxation | 31130 | Service | Tra cứu thông tin thuế, đơn vị hành chính VN, nhóm thuế, tích hợp T-VAN | core |
@nx/signal | 31090 | Service | WebSocket với mã hóa E2E ECDH, Redis Pub/Sub | core |
@nx/invoice | 1190 | Service | Tạo hóa đơn điện tử (IIAPI + T-VAN), base path /v1/api | core, iiapi, t-van |
@nx/search | -- | Library | Tích hợp Typesense, chuyển đổi filter, đồng bộ CDC | core |
@nx/asset | -- | Library | Lưu trữ file Minio/đĩa, quản lý MetaLink | core |
@nx/gateway | -- | Hạ tầng | API gateway và Astro portal (định tuyến, BFF, portal tĩnh) | core |
Các package được đánh dấu
--cho cột Port hoạt động như thư viện nhúng hoặc worker hướng sự kiện thay vì dịch vụ HTTP độc lập.
Kiến trúc Package
Sơ đồ phụ thuộc khi Build
Makefile thực thi theo thứ tự build này. Một package không thể được build cho đến khi tất cả dependencies của nó đã được biên dịch xong.
Sơ đồ phụ thuộc lúc Runtime
Tham chiếu từng Package
@nx/core -- Nền tảng
Mục đích: Nhân dùng chung cung cấp base class, toàn bộ 151 model cơ sở dữ liệu trải dài 14 schema PostgreSQL, tiện ích xuyên suốt, và cấu hình xác thực. Tất cả package khác đều phụ thuộc vào @nx/core.
Các export chính:
| Export | Loại | Mô tả |
|---|---|---|
DefaultApplication | Class | Base application với auth, CORS, Swagger, health check |
SoftDeletableRepository | Class | Repository với soft-delete (đặt deletedAt thay vì xóa vật lý) - re-export từ @venizia/ignis |
PostgresCoreDataSource | DataSource | Data source Drizzle + node-postgres dùng chung |
MigrationRepository | Repository | Theo dõi trạng thái migration trong cơ sở dữ liệu |
IdGenerator | Utility | Singleton sinh Snowflake ID |
IdentityNetworkService | Service | Gọi HTTP liên dịch vụ tới dịch vụ Identity |
useRequestContext() | Function | Trích xuất người dùng đã xác thực, vai trò, và bộ chuẩn hóa response |
CryptoUtility | Utility | Mã hóa/giải mã AES-256-GCM cho thông tin xác thực |
@logged | Decorator | Ghi log đo lường hiệu năng |
bootstrapApplication() | Helper | Factory điểm vào của application |
bootstrapMigration() | Helper | Factory điểm vào của migration |
createAppConfig() | Helper | Bộ dựng cấu hình application tập trung |
createMigrationProcessLoader() | Helper | Bộ import tiến trình migration động |
Hằng số:
| Hằng số | Giá trị |
|---|---|
AppFixedRoles | SUPER_ADMIN (999), ADMIN (900), OPERATOR (600), OWNER/organizer-owner (500), CASHIER (110), EMPLOYEE (100), CUSTOMER (10), GUEST (1) |
MerchantTypes | DEFAULT, TICKET, FNB, THEATER |
PaymentProviders | VNPAY_QR_MMS, SYSTEM |
InvoiceProviders | T_VAN, IIAPI |
TIP
Tài liệu chi tiết: @nx/core
@nx/identity -- Xác thực và Phân quyền
Mục đích: Xác thực người dùng, phân quyền, RBAC, và quản lý nhân viên. Chạy như một dịch vụ HTTP độc lập trên cổng 31010.
Các service:
| Service | Trách nhiệm |
|---|---|
AuthenticationService | Đăng nhập, đăng ký, đổi mật khẩu |
UserService | Tạo người dùng liền mạch (user + identifiers + profile + roles) |
EmployeeService | Quản lý nhân viên với ánh xạ organizer/merchant |
MailVerificationService | Xác minh email với mã 6 chữ số và token |
Chiến lược xác thực: JWT, Basic (qua IGNIS AuthenticateComponent)
Loại định danh: USERNAME, EMAIL, PHONE_NUMBER, USER_NUMBER, NX_AUTH
Giới hạn xác minh Email:
- Mã 6 chữ số: hết hạn sau 10 phút, tối đa 3 lần thử
- Token 32 byte: hết hạn sau 24 giờ
- Giới hạn tốc độ: thời gian chờ 60 giây, 5 lần gửi lại/ngày, khóa 15 phút
TIP
Tài liệu chi tiết: @nx/identity
@nx/commerce -- Danh mục sản phẩm và Định giá
Mục đích: Quản lý sản phẩm, engine định giá động, đăng ký merchant, và hệ thống danh mục. Chạy trên cổng 31020. Tích hợp asset storage, inventory tracking, và Typesense search.
Các service:
| Service | Trách nhiệm |
|---|---|
ProductService | Tạo aggregate (info, identifiers, variants) |
ProductVariantService | Quản lý variant với tích hợp định giá |
FareService | Định giá tĩnh/động với đánh giá quy tắc theo ngữ cảnh |
MerchantService | Đăng ký merchant với danh mục và kênh bán hàng |
Engine định giá:
| Khái niệm | Mô tả |
|---|---|
Fare | Điểm giá với số tiền, trạng thái, kích hoạt theo thời gian |
FareRule | Điều kiện động (số lượng, ngày, ngữ cảnh tùy chỉnh) |
| Rule Operators | EQ, NE, GT, GTE, LT, LTE, IN, NIN |
| Rule Types | OVERRIDE (dừng đánh giá), DISCOUNT, MARKUP |
Các component tích hợp: ApplicationAssetComponent, ApplicationInventoryComponent, ApplicationSearchComponent, NxTVanComponent
TIP
Tài liệu chi tiết: @nx/commerce
@nx/sale -- Quản lý đơn hàng
Mục đích: Vòng đời đơn hàng từ giỏ hàng đến hoàn thành, xác thực checkout, và tích hợp thanh toán qua MQ-Pay. Chạy trên cổng 31030.
Vòng đời đơn hàng:
Các service:
| Service | Trách nhiệm |
|---|---|
SaleOrderService | Tạo đơn, thêm item, hủy đơn |
CheckoutService | Chuyển DRAFT sang PROCESSING, xác thực |
SaleOrderItemService | Cập nhật item theo lô với tự động gộp |
PaymentWebhookService | Xử lý callback trạng thái thanh toán MQ-Pay |
Giới hạn đơn hàng: Tối đa 9,999 số lượng mỗi item. Tối đa 100 item mỗi đơn hàng.
Các component: RedisComponent (cache + BullMQ + Pub/Sub), QueueComponent, ApplicationWebSocketComponent
TIP
Tài liệu chi tiết: @nx/sale
@nx/inventory -- Quản lý kho
Mục đích: Theo dõi kho đa vị trí, xử lý đơn đặt hàng, và nhật ký kiểm toán. Hoạt động như thư viện nhúng được sử dụng bởi @nx/commerce.
Các service:
| Service | Trách nhiệm |
|---|---|
InventoryService | Tạo/cập nhật tồn kho cho product variant |
PurchaseOrderService | Quy trình PO: DRAFT sang PROCESSING sang CONFIRMED sang COMPLETED |
PurchaseOrderItemService | Quản lý dòng item của PO |
Các chỉ số kho:
| Trường | Ý nghĩa |
|---|---|
quantityOnHand | Tổng tồn kho vật lý |
quantityAvailable | Tồn kho trừ đã giữ chỗ (sẵn sàng để bán) |
quantityReserved | Đã phân bổ cho đơn đang chờ |
Loại theo dõi (20 loại đã định nghĩa sẵn):
- Nhập kho: STOCK_IN, PURCHASE, TRANSFER_IN, RETURN_FROM_CUSTOMER, ADJUSTMENT_IN
- Xuất kho: STOCK_OUT, SALE, TRANSFER_OUT, RETURN_TO_VENDOR, EXPIRED, LOST, DAMAGED
- Trung lập: INVENTORY_COUNT, ADJUSTMENT_NEUTRAL
@nx/search -- Tích hợp Typesense
Mục đích: Tìm kiếm thời gian thực do Typesense cung cấp với chuyển đổi filter IGNIS sang query Typesense tự động. Dữ liệu chảy từ PostgreSQL qua Debezium CDC.
Các collection: products, organizers, merchants, categories, devices, sale-channels
Các service:
| Service | Trách nhiệm |
|---|---|
SearchService | Tìm kiếm lõi với chuyển đổi filter |
BaseTypesenseSearchService | Base trừu tượng cho các triển khai tìm kiếm tùy chỉnh |
Các toán tử TypesenseConverter: eq, neq, gt, gte, lt, lte, between, inq (IN), nin (NOT IN), and, or
Biến môi trường: APP_ENV_TYPESENSE_API_KEY, APP_ENV_TYPESENSE_NODES (định dạng: protocol:host:port, phân tách bằng dấu phẩy)
@nx/asset -- Lưu trữ Media
Mục đích: Lưu trữ file với 2 backend (Minio tương thích S3 + local disk) với theo dõi metadata qua entity MetaLink.
Cấu hình lưu trữ:
| Backend | Endpoint | Trường hợp sử dụng |
|---|---|---|
| Minio | /assets | Media tải lên (hình ảnh, tài liệu) |
| Local disk | /resources | Tài nguyên tĩnh (template, banner) |
Các trường MetaLink: bucketName, objectName, link (presigned URL), mimetype, size, etag, storageType, principalId, principalType
TIP
Tài liệu chi tiết: @nx/asset
@nx/finance -- Theo dõi tài chính
Mục đích: Theo dõi thu/chi với quản lý ví. Hướng sự kiện -- lắng nghe các sự kiện commerce và payment để tự động tạo bản ghi tài chính.
Các service:
| Service | Trách nhiệm |
|---|---|
FinanceWorkerService | Bộ xử lý sự kiện và hàng đợi cho mọi nghiệp vụ tài chính |
Các phương thức FinanceWorkerService:
| Phương thức | Kích hoạt | Hành động |
|---|---|---|
handleCommerceInitialized() | Sự kiện COMMERCE_INITIALIZED | Tạo ví Cash mặc định cho merchant mới |
handlePaymentSuccess() | Sự kiện PAYMENT_SUCCESS | Tạo giao dịch INCOME |
handlePurchaseOrderReceived() | Job hàng đợi PURCHASE_ORDER_RECEIVED | Tạo giao dịch EXPENSE |
Loại ví: CASH, BANK, EWALLET, CREDIT_CARD
Loại giao dịch: INCOME, EXPENSE, TRANSFER
Các controller:
| Controller | Path | Loại |
|---|---|---|
FinanceWalletController | /finance-wallets | ControllerFactory CRUD |
FinanceCategoryController | /finance-categories | ControllerFactory CRUD |
FinanceTransactionController | /finance-transactions | ControllerFactory CRUD |
@nx/payment -- Điều phối thanh toán
Mục đích: Lớp cầu nối giữa MQ-Pay và ứng dụng. Quản lý cấu hình webhook, tải và giải mã thông tin xác thực thanh toán, và phân phối sự kiện webhook với logic retry.
Các service:
| Service | Trách nhiệm |
|---|---|
PaymentConfigurationService | Lấy và giải mã cấu hình thanh toán từ bảng Configuration |
WebhookDispatcherService | Phân phối webhook fire-and-forget với exponential backoff |
Các controller:
| Controller | Path | Loại |
|---|---|---|
WebhookConfigController | /webhook-configs | ControllerFactory CRUD |
Nhà cung cấp được hỗ trợ: VNPAY_QR_MMS, VNPAY_PHONE_POS
Migration seed: payment-0001-seed-vnpay-qr-mms-configuration, payment-0002-seed-vnpay-phone-pos-configuration
TIP
Tài liệu chi tiết: @nx/payment
@nx/signal -- Dịch vụ WebSocket
Mục đích: Giao tiếp thời gian thực tập trung với mã hóa đầu cuối. Stateless (không có database, không có migration). Sử dụng Redis Pub/Sub để phân phối message giữa các instance.
Các service:
| Phương thức | Mô tả |
|---|---|
broadcast({ topic, data }) | Gửi tới tất cả client đang kết nối trên mọi instance |
sendToRoom({ room, topic, data }) | Gửi tới tất cả client trong một room |
sendToClient({ clientId, topic, data }) | Gửi tới một client cụ thể (cục bộ hoặc từ xa qua Redis) |
disconnectClient({ clientId }) | Buộc đóng kết nối của một client |
REST API (base: /socket/websocket/clients):
| Method | Path | Auth | Mô tả |
|---|---|---|---|
| GET | /status | None | Sẵn sàng server + số lượng client |
| GET | / | JWT/Basic | Liệt kê client đang kết nối |
| POST | /broadcast | JWT/Basic | Phát sóng tới tất cả client |
| POST | /rooms/:roomName/send | JWT/Basic | Gửi tới một room |
| POST | /:clientId/send | JWT/Basic | Gửi tới client cụ thể |
| POST | /:clientId/disconnect | JWT/Basic | Ngắt kết nối một client |
Mã hóa: Trao đổi khóa ECDH P-256, mã hóa AES-256-GCM theo từng message. WebSocket endpoint: /stream.
Chế độ Redis: Single instance (mặc định) hoặc Cluster mode qua APP_ENV_WEBSOCKET_REDIS_MODE.
TIP
Tài liệu chi tiết: @nx/signal
@nx/invoice -- Tạo hóa đơn điện tử
Mục đích: Tích hợp hóa đơn điện tử Việt Nam thông qua IIAPI (VNPAY viiAPI) và nhà cung cấp T-VAN. Hỗ trợ hóa đơn GTGT, hóa đơn bán hàng, hóa đơn POS, v.v.
Phụ thuộc: @nx/core, @nx/iiapi (third-party), @nx/t-van (third-party)
TIP
Tài liệu chi tiết: @nx/invoice
Kiến trúc phân lớp
Mọi dịch vụ backend đều tuân theo pattern Controller-Service-Repository được thực thi bởi framework IGNIS.
| Lớp | Trách nhiệm | IGNIS Base Class |
|---|---|---|
| Controller | Vận chuyển HTTP, xác thực đầu vào qua Zod, định dạng response | ControllerFactory.defineCrudController() hoặc tùy chỉnh |
| Service | Logic nghiệp vụ thuần, điều phối, xử lý sự kiện | BaseService |
| Repository | Trừu tượng truy cập cơ sở dữ liệu, query Drizzle ORM | SoftDeletableRepository hoặc DefaultCRUDRepository |
| Component | Mối quan tâm xuyên suốt: Redis, queue, tích hợp bên ngoài | BaseComponent |
| DataSource | Pool kết nối và thiết lập connector Drizzle | BaseDataSource |
Luồng request
1. HTTP Request --> Controller (route handler)
2. Controller validates input with Zod schemas via @hono/zod-openapi
3. Controller calls Service layer via DI
4. Service executes business logic
5. Service calls Repository for data access
6. Repository executes Drizzle ORM queries against PostgreSQL
7. Response flows back through layersTổng quan cơ sở dữ liệu
Tất cả model cơ sở dữ liệu được định nghĩa trong @nx/core dưới src/models/schemas/. Các service dùng chung một kết nối PostgresCoreDataSource.
14 schema PostgreSQL, 151 entity
| Schema | Models | Số lượng | Entity chính |
|---|---|---|---|
helpdesk | Hỗ trợ khách hàng | 30 | Agent, AgentGroup, AgentGroupMember, Article, ArticleCategory, AssignmentRule, SlaEscalation, Notification, NotificationTemplate, FeatureRequest, Compensation, v.v. |
public | Miền tổng quát | 26 | Product, ProductInfo, ProductIdentifier, ProductVariant, ProductOption, Merchant, Organizer, Category, Device, SaleChannel, Configuration, Setting, MetaLink, ReceiptTemplate, WebhookConfig, v.v. |
inventory | Quản lý kho | 17 | InventoryItem, InventoryLocation, InventoryStock, InventoryTracking, Material, MaterialRecipe, PurchaseOrder, PurchaseOrderItem, ProductionOrder, UnitOfMeasure, Vendor, VendorItem, v.v. |
sale | Đơn hàng | 21 | SaleOrder, SaleItem, SaleCheck, SaleCheckItem, Customer, KitchenStation, KitchenTicket, KitchenTicketItem, PointTransaction, PosSession, PosSessionReport, Reservation, EntitlementPolicy, v.v. |
invoice | Hóa đơn điện tử | 9 | Invoice, InvoiceIssuance, InvoiceRequest, InvoiceProvider, InvoiceProviderConfig, InvoiceAuditTracing, InvoiceConfigMapping, MerchantInvoiceProfile, MerchantProfileEnrollment |
pricing | Engine định giá | 9 | Fare, FareSet, Cost, Promotion, PromotionMethod, Rule, Tax, TaxSet, TaxType |
identity | Xác thực & người dùng | 8 | User, UserCredential, UserIdentifier, UserProfile, UserConfiguration, Role, Permission, PolicyDefinition |
ledger | Sổ kế toán HKD | 8 | Ledger, LedgerIdentifier, LedgerJob, LedgerSnapshot, LedgerSnapshotEntry, LedgerTaxConfig, MerchantTaxConfig, TaxTier |
finance | Theo dõi tài chính | 6 | FinanceAccount, FinanceCategory, FinanceTransaction, FinanceVoucher, FinanceVoucherSequence, PaymentIntegration |
tax | Thuế & hành chính VN | 6 | TaxGroup, TaxGroupItem, TaxInfo, VnAdministrativeUnit, VnProvince, VnWard |
licensing | Quản lý license | 5 | Activation, License, LicenseEvent, Policy, PolicyFeature |
allocation | Xếp chỗ sự kiện | 4 | AllocationLayout, AllocationUnit, AllocationUsage, AllocationZone |
outreach | Người đăng ký | 2 | Inquiry, Subscriber |
payment | Namespace dự trữ | 0 | - |
Pattern Soft-Delete
Tất cả entity có thể xóa đều sử dụng SoftDeletableRepository từ @nx/core. Thay vì xóa vật lý, một timestamp deletedAt được đặt. Bản ghi có thể khôi phục bằng restoreById().
// Schema includes deletedAt column
deletedAt: (timestamp('deleted_at', { withTimezone: true }),
// Repository extends SoftDeletableRepository
@repository({ dataSource: PostgresCoreDataSource, model: Category })
export class CategoryRepository extends SoftDeletableRepository<
typeof Category.schema,
TCategory,
TCategoryPersist
> {});
// deleteById sets deletedAt instead of removing the row
// restoreById sets deletedAt back to null
// Pass { shouldHardDelete: true } for physical deletionKiến trúc hướng sự kiện
Hệ thống sử dụng hai pattern messaging bổ sung cho nhau: Redis Pub/Sub cho phát sóng sự kiện thời gian thực và BullMQ cho xử lý job bất đồng bộ đáng tin cậy.
Các kênh Redis Pub/Sub
| Channel | Publisher | Subscribers | Mục đích |
|---|---|---|---|
PaymentSuccess | Payment / Sale | Finance | Ghi nhận giao dịch thu khi thanh toán thành công |
SellerRegistered | Identity | Commerce | Khởi tạo mặc định merchant khi người bán đăng ký mới |
CommerceInitialized | Commerce | Finance | Tạo ví Cash mặc định cho merchant mới |
Hệ thống hàng đợi BullMQ
Mỗi loại hàng đợi sử dụng 3 partition (P01, P02, P03) để phân phối tải.
| Package | Loại hàng đợi | Mục đích |
|---|---|---|
| Commerce | 3 loại | Đánh chỉ mục sản phẩm, đồng bộ danh mục, thiết lập merchant |
| Finance | 2 loại | PURCHASE_ORDER_RECEIVED (ghi nhận chi phí), xử lý giao dịch |
| Inventory | 1 loại | Xử lý điều chỉnh tồn kho |
| Sale | 2 loại | Lập lịch hết hạn đơn hàng, xác nhận thanh toán |
| MQ-Pay | 2 loại (scheduler, confirmation) | Hết hạn lần thử thanh toán, xác nhận IPN/webhook |
Ví dụ luồng sự kiện
Bảo mật
Xác thực và Phân quyền
| Cơ chế | Vị trí | Mô tả |
|---|---|---|
| JWT Authentication | DefaultApplication.configureSecurity() | Xác thực dựa trên token cho truy cập API |
| Basic Authentication | DefaultApplication.configureSecurity() | Username/password qua IdentityNetworkService |
| bcrypt Hashing | @nx/identity | Lưu mật khẩu với bcrypt (^6.0.0) |
| Role-Based Access | Tất cả controller | 8 vai trò cố định với mức ưu tiên số |
Các vai trò mặc định
| Vai trò | Mã | Phạm vi |
|---|---|---|
| SUPER_ADMIN | 999 | Toàn quyền hệ thống |
| ADMIN | 900 | Vận hành quản trị |
| OPERATOR | 600 | Quản lý vận hành |
| OWNER (organizer-owner) | 500 | Truy cập theo phạm vi organizer |
| CASHIER | 110 | Thu ngân / nhân viên POS |
| EMPLOYEE | 100 | Truy cập theo phạm vi nhân viên |
| CUSTOMER | 10 | Khách hàng cuối |
| GUEST | 1 | Chưa xác thực / toàn cục |
Mã hóa
| Cơ chế | Thuật toán | Sử dụng |
|---|---|---|
| WebSocket E2E | ECDH P-256 + AES-256-GCM | Package Signal -- dẫn xuất khóa theo client |
| Credential Storage | AES-256-GCM | CryptoUtility -- bí mật nhà cung cấp thanh toán |
| Password Hashing | bcrypt | Package Identity -- thông tin xác thực người dùng |
Các pattern của IGNIS Framework
Vòng đời Application
Mọi service mở rộng DefaultApplication cung cấp xác thực, CORS, Swagger, và cấu hình health check sẵn có.
// packages/sale/src/application.ts
import {
createAppConfig,
VerifierApplication,
MigrationRepository,
PostgresCoreDataSource,
} from '@nx/core';
import { CoreBindings, IApplicationInfo } from '@venizia/ignis';
export const appConfig = createAppConfig();
export class Application extends VerifierApplication {
override getAppInfo(): IApplicationInfo {
return {
name: '@nx/sale',
version: '0.0.0',
description: 'Sale order management with payment integration',
author: { name: 'Nexpando', email: 'contact@nexpando.com' },
};
}
override getProjectRoot(): string {
const projectRoot = __dirname;
this.bind<string>({ key: CoreBindings.APPLICATION_PROJECT_ROOT }).toValue(projectRoot);
return projectRoot;
}
override configureComponents(): void {
super.configureComponents(); // HealthCheck + Swagger + Auth
this.component(RedisComponent);
this.component(QueueComponent);
}
override preConfigure(): void {
super.preConfigure();
this.dataSource(PostgresCoreDataSource);
this.repository(SaleOrderRepository);
this.service(SaleOrderService);
this.service(CheckoutService);
this.controller(SaleOrderController);
}
}Bootstrap Helper
Điểm vào của application và migration được chuẩn hóa qua các hàm helper của @nx/core.
// packages/sale/src/index.ts -- Application entry point
import { bootstrapApplication } from '@nx/core';
import { resolve } from 'node:path';
import { appConfig, Application } from './application';
bootstrapApplication({
ApplicationClass: Application,
config: appConfig,
options: { bannerPath: resolve(process.cwd(), 'resources/banner.txt') },
});// packages/sale/src/migrations/processes/migration-process.ts
import { createMigrationProcessLoader } from '@nx/core';
export const getMigrationProcesses = createMigrationProcessLoader({
seedPaths: ['sale-0001-seed-data', 'sale-0002-seed-channels'],
importFn: path => import(`../processes/${path}.js`),
});Dependency Injection
IGNIS sử dụng constructor injection với decorator @inject(). Binding key tuân theo quy ước namespace.ClassName.
// Service with repository injection
import { BaseService, BindingKeys, BindingNamespaces, inject } from '@venizia/ignis';
export class CheckoutService extends BaseService {
constructor(
@inject({
key: BindingKeys.build({
namespace: BindingNamespaces.REPOSITORY,
key: SaleOrderRepository.name,
}),
})
private readonly _saleOrderRepository: SaleOrderRepository,
@inject({
key: BindingKeys.build({
namespace: BindingNamespaces.SERVICE,
key: SaleSocketEventService.name,
}),
})
private readonly _saleSocketEventService: SaleSocketEventService,
) {
super({ scope: CheckoutService.name });
}
}Helper BindingKeys.build() tạo ra key như repositories.SaleOrderRepository và services.SaleSocketEventService. Bạn cũng có thể viết binding key dưới dạng chuỗi thuần:
@inject({ key: 'repositories.SaleOrderRepository' })
private readonly saleOrderRepository: SaleOrderRepository,Pattern Component
Component đóng gói các mối quan tâm xuyên suốt (Redis, queue, dịch vụ bên ngoài) và đăng ký binding trong hook vòng đời binding().
import { BaseApplication, BaseComponent, CoreBindings, inject, RedisHelper } from '@venizia/ignis';
export class RedisComponent extends BaseComponent {
constructor(
@inject({ key: CoreBindings.APPLICATION_INSTANCE })
protected application: BaseApplication,
) {
super({
scope: RedisComponent.name,
initDefault: { enable: true, container: application },
bindings: {},
});
}
override async binding(): Promise<void> {
const cacheRedis = new RedisHelper({ name: 'cache-redis', host: 'localhost', port: 6379 });
await cacheRedis.connect();
this.application.bind({ key: BindingKeys.APPLICATION_REDIS_CACHE }).toValue(cacheRedis);
}
}ControllerFactory (Auto CRUD)
ControllerFactory.defineCrudController() tạo một controller CRUD đầy đủ với tài liệu OpenAPI, xác thực, và các endpoint REST chuẩn.
import {
ControllerFactory,
controller,
inject,
BindingKeys,
BindingNamespaces,
} from '@venizia/ignis';
const _Controller = ControllerFactory.defineCrudController({
repository: { name: FinanceWalletRepository.name },
authenticate: { strategies: ['jwt', 'basic'] },
controller: {
name: 'FinanceWalletController',
basePath: '/finance-wallets',
isStrict: { path: true, requestSchema: true },
},
entity: () => FinanceWallet,
});
@controller({ path: '/finance-wallets' })
export class FinanceWalletController extends _Controller {
constructor(
@inject({
key: BindingKeys.build({
key: FinanceWalletRepository.name,
namespace: BindingNamespaces.REPOSITORY,
}),
})
financeWalletRepository: FinanceWalletRepository,
) {
super(financeWalletRepository);
}
// Override individual methods for custom logic (role-based filtering, etc.)
@logged()
override async findById(opts: { context: TRouteContext<Env> }) {
// Custom implementation...
}
}Database Transaction
Repository hỗ trợ các thao tác giao dịch thông qua data source.
await this.repository.dataSource.withTransaction(async tx => {
await this.repository.create({ data: orderData, options: { transaction: tx } });
await this.itemRepository.create({ data: itemData, options: { transaction: tx } });
});Cấu hình môi trường
Tất cả package sử dụng dotenv-flow để quản lý môi trường. Các biến tuân theo quy ước tiền tố APP_ENV_*.
Các file môi trường
| File | Mục đích | Git theo dõi |
|---|---|---|
.env.example | Template với tất cả biến bắt buộc | Có |
.env.development | Cài đặt development | Có |
.env.test | Môi trường test | Có |
.env.local | Ghi đè cục bộ | Không (gitignored) |
Biến môi trường phổ biến
# Application
APP_ENV_NODE_ENV=development
APP_ENV_APPLICATION_NAME=nx-sale
APP_ENV_APPLICATION_SECRET=<secret>
APP_ENV_SERVER_HOST=0.0.0.0
APP_ENV_SERVER_PORT=31030
APP_ENV_SERVER_BASE_PATH=/api
# Authentication
APP_ENV_JWT_SECRET=<jwt-secret>
APP_ENV_JWT_EXPIRES_IN=3600
# PostgreSQL
APP_ENV_POSTGRES_HOST=localhost
APP_ENV_POSTGRES_PORT=5432
APP_ENV_POSTGRES_DATABASE=bana
APP_ENV_POSTGRES_USERNAME=postgres
APP_ENV_POSTGRES_PASSWORD=password
# Redis (Cache)
APP_ENV_CACHE_REDIS_HOST=localhost
APP_ENV_CACHE_REDIS_PORT=6379
APP_ENV_CACHE_REDIS_DB=0
# Redis (BullMQ Queues)
APP_ENV_BULLMQ_REDIS_HOST=localhost
APP_ENV_BULLMQ_REDIS_PORT=6379
APP_ENV_BULLMQ_REDIS_DB=1
# Redis (Pub/Sub)
APP_ENV_PUBSUB_SUBSCRIBER_REDIS_HOST=localhost
APP_ENV_PUBSUB_PUBLISHER_REDIS_HOST=localhost
# Minio (Assets)
APP_ENV_MINIO_HOST=localhost
APP_ENV_MINIO_API_PORT=9000
APP_ENV_MINIO_ACCESS_KEY=minioadmin
APP_ENV_MINIO_SECRET_KEY=minioadmin
# Typesense (Search)
APP_ENV_TYPESENSE_API_KEY=xyz
APP_ENV_TYPESENSE_NODES=http:localhost:8108
# Snowflake ID
APP_ENV_SNOWFLAKE_WORKER_ID=1
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT=1704067200000
# Service URLs
APP_ENV_IDENTITY_SERVICE_URL=http://localhost:31010
APP_ENV_COMMERCE_SERVICE_URL=http://localhost:31020Quy trình phát triển
Lệnh build
| Lệnh | Mô tả |
|---|---|
make install | Cài đặt tất cả dependencies (bun install) |
make build | Build mọi thứ theo thứ tự phụ thuộc |
make build-packages | Chỉ build packages/* |
make build-3rd | Chỉ build third-parties/* |
make core | Build @nx/core |
make sale | Build @nx/sale |
make commerce | Build @nx/commerce |
make identity | Build @nx/identity |
make finance | Build @nx/finance |
make payment | Build @nx/payment |
make signal | Build @nx/signal |
WARNING
Luôn sử dụng bun run rebuild trong một package. Không chạy tsc trực tiếp -- path alias (@/common, @/services) yêu cầu bước xử lý sau tsc-alias.
Development Server
| Lệnh | Service | Port |
|---|---|---|
make dev-sale | Sale service | 31030 |
make dev-commerce | Commerce service | 31020 |
make dev-identity | Identity service | 31010 |
make dev-finance | Finance service | 31040 |
make dev-payment | Payment service | 31080 |
make dev-signal | Signal (WebSocket) | 31090 |
Lệnh từng package
cd packages/sale # Navigate to package
bun run rebuild # Clean + build (tsc + tsc-alias)
bun run server:dev # Start with .env.development
bun run test # Run tests (requires .env.test)
bun run test:watch # Watch mode
bun run lint:fix # ESLint + Prettier auto-fix
bun run migrate:dev # Apply database migrationsTest
# Run all tests for a package
cd packages/sale && bun run rebuild && bun run test
# Run a single test file
bun test --env-file=.env.test dist/__tests__/path/to/file.test.jsLint
| Lệnh | Phạm vi |
|---|---|
make lint | Mọi thứ |
make lint-packages | Tất cả package |
make lint-3rd | Tất cả third-party |
make lint-sale | Chỉ @nx/sale |
make lint-finance | Chỉ @nx/finance |
make lint-payment | Chỉ @nx/payment |
make lint-signal | Chỉ @nx/signal |
Git Hook
make setup-tools # Configure git to use .githooks directory
make pre-commit # Run all linting checks (used by pre-commit hook)Tiêu chuẩn API
Quy ước route
| Method | Mẫu | Mục đích |
|---|---|---|
GET | /resources | Liệt kê với lọc, phân trang |
GET | /resources/:id | Lấy một resource |
GET | /resources/count | Đếm resource khớp |
POST | /resources | Tạo resource |
PUT | /resources/:id | Cập nhật toàn bộ |
PATCH | /resources/:id | Cập nhật một phần |
DELETE | /resources/:id | Soft delete (đặt deletedAt) |
Tài liệu OpenAPI
Mỗi service cung cấp tài liệu Swagger/OpenAPI:
- OpenAPI JSON:
/doc/openapi.json - Scalar Explorer:
/doc/explorer - Health Check:
/health
Liên kết nhanh
Tài liệu package
| Package | Liên kết |
|---|---|
| @nx/core | Kiến trúc, component, cấu hình, cơ sở dữ liệu, tiện ích |
| @nx/identity | Xác thực, phân quyền, quản lý người dùng |
| @nx/commerce | Sản phẩm, định giá, merchant |
| @nx/sale | Đơn hàng, checkout, thanh toán |
| @nx/payment | Cấu hình webhook, điều phối thanh toán |
| @nx/signal | WebSocket, mã hóa, nhắn tin thời gian thực |
| @nx/asset | Lưu trữ file, quản lý MetaLink |
| @nx/invoice | Tạo hóa đơn điện tử |
| API Gateway | Định tuyến và middleware của Gateway |
Tham khảo bên ngoài
| Tài nguyên | Liên kết |
|---|---|
| IGNIS Framework | https://venizia-ai.github.io/ignis/ |
| Hono | https://hono.dev |
| Drizzle ORM | https://orm.drizzle.team |
| Zod | https://zod.dev |
| BullMQ | https://docs.bullmq.io |
| Typesense | https://typesense.org/docs |