Skip to content

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ả 14 package trong thư mục packages/, cơ sở dữ liệu PostgreSQL dùng chung với 10 schema, hạ tầng event-driven (Kafka + Redis Pub/Sub + 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ệ

Công nghệ lõi

TechnologyVersionPurpose
Bun>=1.3.8JavaScript/TypeScript runtime
TypeScript~5.9.3Static type system
IGNIS Framework0.0.7-7IoC container, DI, application lifecycle
IGNIS Helpers0.0.6-7Framework utility extensions
Hono4.11.3Lightweight HTTP framework
Drizzle ORM^0.45.1Type-safe SQL ORM
Drizzle Kit^0.31.8Schema migrations CLI
Drizzle Zod^0.8.3Drizzle-to-Zod schema bridge
Zod4.1.13Runtime schema validation
PostgreSQL16+Primary relational database
Redis7+Caching, Pub/Sub, BullMQ

API và tài liệu

TechnologyVersionPurpose
@hono/zod-openapi1.2.0OpenAPI route definitions
@scalar/hono-api-reference^0.9.28Interactive API explorer UI

Thư viện hỗ trợ

TechnologyVersionPurpose
pg^8.16.3PostgreSQL client driver
bcrypt^6.0.0Password hashing (Identity)
dayjs^1.11.19Date/time manipulation
BullMQ^5.14.3Distributed job queues
dotenv-flow^4.1.0Environment variable management
nodemailer^7.0.12Transactional email

Cấu trúc hệ thống

Tất cả 14 package Backend

PackagePortRoleKey ResponsibilitiesPrimary Dependencies
@nx/core--FoundationBase classes, DB models trên 10 schema, utilities, auth config--
@nx/identity31010ServiceAuthentication, authorization, user management, RBACcore
@nx/commerce31020ServiceProducts, pricing engine, merchants, categories, CDCcore, asset, inventory, search
@nx/sale31030ServiceOrder lifecycle, checkout, kitchen orders, payment orchestrationcore, mq-pay
@nx/inventory31050ServiceStock tracking, purchase orders, vendor managementcore
@nx/finance31040ServiceWallets, income/expense tracking, financial categoriescore
@nx/pricing31070ServiceFare sets, tax engine, promotions, pricing rulescore
@nx/payment31080ServiceWebhook config, credential loading, payment dispatchcore, mq-pay
@nx/ledger31060ServiceTạo sổ kế toán HKD (PDF/XLSX), mã hóa, S3core
@nx/outreach31110ServiceĐăng ký nhận tin, biểu mẫu liên hệcore
@nx/licensing31120ServiceQuản lý license theo policy, ký chứng chỉ, pipeline xác thựccore
@nx/signal31090ServiceWebSocket with ECDH E2E encryption, Redis Pub/Subcore
@nx/invoice--ServiceE-invoice generation (IIAPI + T-VAN)core, iiapi, t-van
@nx/search--LibraryTypesense integration, filter conversion, CDC synccore
@nx/asset--LibraryMinio/disk file storage, MetaLink managementcore

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

Tầng Nền tảng
🏗️
@nx/core
Lớp cơ sở, 55 DB model trên 7 schema, tiện ích, chiến lược xác thực, bootstrap helper
Thư viện Chia sẻ — Nhúng vào service, không có HTTP server độc lập
📦
@nx/asset
Lưu trữ file Minio & đĩa
🔍
@nx/search
Tích hợp tìm kiếm Typesense
📊
@nx/inventory
Theo dõi tồn kho & đơn mua hàng
Service Độc lập — HTTP server và/hoặc worker hướng sự kiện
🔐
@nx/identity
Xác thực & phân quyền RBAC
🛒
@nx/commerce
Sản phẩm & hệ thống định giá
🧾
@nx/sale
Đơn hàng & thanh toán
💰
@nx/finance
Ví & thu chi tài chính
💳
@nx/payment
Webhook & phân phối thông tin xác thực
📡
@nx/signal
WebSocket & mã hóa E2E
📄
@nx/invoice
Hóa đơn điện tử (IIAPI & T-VAN)
🏷️
@nx/pricing
Bộ giá, thuế & khuyến mãi
📒
@nx/ledger
Tạo sổ kế toán HKD
📨
@nx/outreach
Người đăng ký & liên hệ

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ộ 55 model cơ sở dữ liệu trải dài 7 schema PostgreSQL, tiện ích dùng chung, 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:

ExportTypeDescription
DefaultApplicationClassBase application with auth, CORS, Swagger, health checks
SoftDeletableRepositoryClassRepository with soft-delete (sets deletedAt instead of physical delete)
PostgresCoreDataSourceDataSourceShared Drizzle + node-postgres data source
MigrationRepositoryRepositoryTracks migration status in the database
IdGeneratorUtilitySnowflake ID generation singleton
IdentityNetworkServiceServiceCross-service HTTP calls to the Identity service
useRequestContext()FunctionExtracts authenticated user, roles, and response normalizers
CryptoUtilityUtilityAES-256-GCM encryption/decryption for credentials
@loggedDecoratorPerformance measurement logging
bootstrapApplication()HelperApplication entry point factory
bootstrapMigration()HelperMigration entry point factory
createAppConfig()HelperCentralized application configuration builder
createMigrationProcessLoader()HelperDynamic migration process importer

Hằng số:

ConstantValues
FixedUserRolesSUPER_ADMIN (999), ADMIN (998), OPERATOR (997), ORGANIZER_OWNER (899), EMPLOYEE (898)
MerchantTypesDEFAULT, TICKET, FNB, THEATER
PaymentProvidersVNPAY_QR_MMS, SYSTEM
InvoiceProvidersT_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 3001.

Các service:

ServiceResponsibility
AuthenticationServiceSign-in, sign-up, password change
UserServiceAtomic user creation (user + identifiers + profile + roles)
EmployeeServiceEmployee management with organizer/merchant mapping
MailVerificationServiceEmail verification with 6-digit codes and tokens

Chiến lược xác thực: JWT, Basic (via 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 3002. Tích hợp asset storage, inventory tracking, và Typesense search.

Các service:

ServiceResponsibility
ProductServiceAggregate creation (info, identifiers, variants)
ProductVariantServiceVariant management with pricing integration
FareServiceStatic/dynamic pricing with context-based rule evaluation
MerchantServiceMerchant onboarding with categories and sale channels

Engine định giá:

ConceptDescription
FarePrice point with amount, status, time-based activation
FareRuleDynamic condition (quantity, date, custom context)
Rule OperatorsEQ, NE, GT, GTE, LT, LTE, IN, NIN
Rule TypesOVERRIDE (stops evaluation), 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 3003.

Vòng đời đơn hàng:

DRAFT
PROCESSING
PARTIAL
COMPLETED

Các service:

ServiceResponsibility
SaleOrderServiceCreate orders, add items, cancel orders
CheckoutServiceDRAFT to PROCESSING transitions, validation
SaleOrderItemServiceBatch item updates with auto-merge
PaymentWebhookServiceHandle MQ-Pay payment status callbacks

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:

ServiceResponsibility
InventoryServiceCreate/update inventory for product variants
PurchaseOrderServicePO workflow: DRAFT to PROCESSING to CONFIRMED to COMPLETED
PurchaseOrderItemServicePO line item management

Các chỉ số kho:

FieldMeaning
quantityOnHandTotal physical stock
quantityAvailableOn-hand minus reserved (available for sale)
quantityReservedAllocated for pending orders

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

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:

ServiceResponsibility
SearchServiceCore search with filter conversion
BaseTypesenseSearchServiceAbstract base for custom search implementations

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 (format: protocol:host:port, comma-separated)


@nx/asset -- Lưu trữ Media

Mục đích: Lưu trữ file với 2 backend (Minio S3-compatible + local disk) với theo dõi metadata qua entity MetaLink.

Cấu hình lưu trữ:

BackendEndpointUse Case
Minio/assetsUploaded media (images, documents)
Local disk/resourcesStatic resources (templates, banners)

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:

ServiceResponsibility
FinanceWorkerServiceEvent and queue handler for all financial operations

Các phương thức FinanceWorkerService:

MethodTriggerAction
handleCommerceInitialized()COMMERCE_INITIALIZED eventCreates default Cash wallet for new merchant
handlePaymentSuccess()PAYMENT_SUCCESS eventCreates INCOME transaction
handlePurchaseOrderReceived()PURCHASE_ORDER_RECEIVED queue jobCreates EXPENSE transaction

Loại ví: CASH, BANK, EWALLET, CREDIT_CARD

Loại giao dịch: INCOME, EXPENSE, TRANSFER

Các controller:

ControllerPathType
FinanceWalletController/finance-walletsControllerFactory CRUD
FinanceCategoryController/finance-categoriesControllerFactory CRUD
FinanceTransactionController/finance-transactionsControllerFactory 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:

ServiceResponsibility
PaymentConfigurationServiceFetch and decrypt payment configs from Configuration table
WebhookDispatcherServiceFire-and-forget webhook dispatch with exponential backoff

Các controller:

ControllerPathType
WebhookConfigController/webhook-configsControllerFactory 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:

MethodDescription
broadcast({ topic, data })Send to all connected clients across all instances
sendToRoom({ room, topic, data })Send to all clients in a room
sendToClient({ clientId, topic, data })Send to a specific client (local or remote via Redis)
disconnectClient({ clientId })Force-close a client connection

REST API (base: /socket/websocket/clients):

MethodPathAuthDescription
GET/statusNoneServer readiness + client count
GET/JWT/BasicList connected clients
POST/broadcastJWT/BasicBroadcast to all clients
POST/rooms/:roomName/sendJWT/BasicSend to a room
POST/:clientId/sendJWT/BasicSend to specific client
POST/:clientId/disconnectJWT/BasicDisconnect a client

Mã hóa: ECDH P-256 key exchange, AES-256-GCM per-message encryption. WebSocket endpoint: /stream.

Chế độ Redis: Single instance (default) 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.

Controller
Service
Repository
PostgreSQL
LayerResponsibilityIGNIS Base Class
ControllerHTTP transport, input validation via Zod, response formattingControllerFactory.defineCrudController() or custom
ServicePure business logic, orchestration, event handlingBaseService
RepositoryDatabase access abstraction, Drizzle ORM queriesSoftDeletableRepository or DefaultCRUDRepository
ComponentCross-cutting concerns: Redis, queues, external integrationsBaseComponent
DataSourceConnection pooling and Drizzle connector setupBaseDataSource

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 layers

Tổ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.

7 schema PostgreSQL, 55 model

SchemaModelsCountKey Entities
publicGeneral domain30User, UserCredential, UserProfile, Role, Permission, Product, ProductInfo, ProductIdentifier, ProductVariant, Merchant, Organizer, Category, Device, Terminal, SaleChannel, Configuration, Employee, Vendor, MetaLink, MerchantType, CategoryTemplate, etc.
pricingPricing engine7Fare, FareSet, FareRule, Cost, Tax, TaxSet, TaxType
allocationEvent seating4Venue, Section, Seat, Allocation
inventoryStock management8Inventory, PurchaseOrder, PurchaseOrderItem, InventoryTracking, InventoryTrackingType, etc.
saleOrders2SaleOrder, SaleOrderItem
financeFinancial tracking3FinanceWallet, FinanceCategory, FinanceTransaction
paymentWebhook config1WebhookConfig

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().

typescript
// 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 deletion

Kiế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

ChannelPublisherSubscribersPurpose
PaymentSuccessPayment / SaleFinanceRecord income transactions on successful payment
SellerRegisteredIdentityCommerceInitialize merchant defaults on new seller signup
CommerceInitializedCommerceFinanceCreate default Cash wallet for new merchant

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.

PackageQueue TypesPurpose
Commerce3 typesProduct indexing, category sync, merchant setup
Finance2 typesPURCHASE_ORDER_RECEIVED (expense recording), transaction processing
Inventory1 typeStock adjustment processing
Sale2 typesOrder expiration scheduling, payment confirmation
MQ-Pay2 types (scheduler, confirmation)Payment attempt expiration, IPN/webhook confirmation

Ví dụ luồng sự kiện


Bảo mật

Xác thực và Phân quyền

MechanismLocationDescription
JWT AuthenticationDefaultApplication.configureSecurity()Token-based auth for API access
Basic AuthenticationDefaultApplication.configureSecurity()Username/password via IdentityNetworkService
bcrypt Hashing@nx/identityPassword storage with bcrypt (^6.0.0)
Role-Based AccessAll controllers5 fixed roles with numeric precedence

Các vai trò mặc định

RoleCodeScope
SUPER_ADMIN999Full system access
ADMIN998Administrative operations
OPERATOR997Operational management
ORGANIZER_OWNER899Organizer-scoped access
EMPLOYEE898Employee-scoped access

Mã hóa

MechanismAlgorithmUsage
WebSocket E2EECDH P-256 + AES-256-GCMSignal package -- per-client key derivation
Credential StorageAES-256-GCMCryptoUtility -- payment provider secrets
Password HashingbcryptIdentity package -- user credentials

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ó.

typescript
// packages/sale/src/application.ts
import { createAppConfig, DefaultApplication, MigrationRepository, PostgresCoreDataSource } from '@nx/core';
import { CoreBindings, IApplicationInfo } from '@venizia/ignis';

export const appConfig = createAppConfig();

export class Application extends DefaultApplication {
  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.

typescript
// 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') },
});
typescript
// 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.

typescript
// 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.SaleOrderRepositoryservices.SaleSocketEventService. Bạn cũng có thể viết binding key dưới dạng chuỗi thuần:

typescript
@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().

typescript
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.

typescript
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.

typescript
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

FilePurposeGit Tracked
.env.exampleTemplate with all required variablesYes
.env.developmentDevelopment settingsYes
.env.testTest environmentYes
.env.localLocal overridesNo (gitignored)

Biến môi trường phổ biến

bash
# 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=3003
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:3001
APP_ENV_COMMERCE_SERVICE_URL=http://localhost:3002

Quy trình phát triển

Lệnh build

CommandDescription
make installInstall all dependencies (bun install)
make buildBuild everything in dependency order
make build-packagesBuild only packages/*
make build-3rdBuild only third-parties/*
make coreBuild @nx/core
make saleBuild @nx/sale
make commerceBuild @nx/commerce
make identityBuild @nx/identity
make financeBuild @nx/finance
make paymentBuild @nx/payment
make signalBuild @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

CommandServicePort
make dev-sale-orderSale service3003
make dev-commerceCommerce service3002
make dev-identityIdentity service3001
make dev-financeFinance service--
make dev-paymentPayment service--
make dev-signalSignal (WebSocket)--

Lệnh từng package

bash
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 migrations

Test

bash
# 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.js

Lint

CommandScope
make lintEverything
make lint-packagesAll packages
make lint-3rdAll third-parties
make lint-sale-order@nx/sale only
make lint-finance@nx/finance only
make lint-payment@nx/payment only
make lint-signal@nx/signal only

Git Hook

bash
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

MethodPatternPurpose
GET/resourcesList with filtering, pagination
GET/resources/:idGet single resource
GET/resources/countCount matching resources
POST/resourcesCreate resource
PUT/resources/:idFull update
PATCH/resources/:idPartial update
DELETE/resources/:idSoft delete (sets 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

PackageLink
@nx/coreArchitecture, components, configuration, database, utilities
@nx/identityAuthentication, authorization, user management
@nx/commerceProducts, pricing, merchants
@nx/saleOrders, checkout, payments
@nx/paymentWebhook config, payment orchestration
@nx/signalWebSocket, encryption, real-time messaging
@nx/assetFile storage, MetaLink management
@nx/invoiceE-invoice generation
API GatewayGateway routing and middlewares

Tham khảo bên ngoài

ResourceLink
IGNIS Frameworkhttps://venizia-ai.github.io/ignis/
Honohttps://hono.dev
Drizzle ORMhttps://orm.drizzle.team
Zodhttps://zod.dev
BullMQhttps://docs.bullmq.io
Typesensehttps://typesense.org/docs

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.