Skip to content

Kiến trúc Core

1. Tổng quan

@nx/core triển khai kiến trúc phân lớp xây dựng trên nền IGNIS Framework. Mọi microservice backend trong monorepo BANA đều mở rộng BaseApplication dùng chung từ package này - thông qua IssuerApplication (dịch vụ @nx/identity) hoặc VerifierApplication (13 dịch vụ còn lại) - qua đó kế thừa một tập hợp nhất quán các hạng mục hạ tầng dùng chung: xác thực, CORS, health check, tài liệu Swagger, kết nối cơ sở dữ liệu, và giao tiếp liên dịch vụ.

Tài liệu này bao gồm:

  • Kiến trúc phân lớp và cách các primitive của IGNIS ánh xạ tới từng lớp
  • Vòng đời ứng dụng và các lớp cơ sở BaseApplication / IssuerApplication / VerifierApplication
  • Các mẫu dependency injection
  • Các mẫu component, controller, repository, và service
  • Kiến trúc hướng sự kiện (Kafka + Debezium CDC; BullMQ cho async job)
  • Các bootstrap helper cho điểm khởi chạy ứng dụng và migration
  • Giao tiếp liên dịch vụ thông qua IdentityNetworkService
  • Luồng xác thực (JWT + Basic)
  • Chuỗi phụ thuộc giữa các package

2. Kiến trúc Phân lớp

Tất cả dịch vụ backend đều tuân theo kiến trúc năm lớp. Mỗi lớp có một trách nhiệm duy nhất và chỉ giao tiếp với các lớp lân cận trực tiếp.

LớpThành phầnMô tả
ApplicationBaseApplicationVòng đời preConfigure() · CORS · BodyLimit 100 MB · Swagger UI · được kế thừa bởi IssuerApplication / VerifierApplication
Bootstrap HelpersbootstrapApplication() · bootstrapMigration() · createAppConfig() · createMigrationProcessLoader()
Built-in ComponentsHealthCheck GET /health · Swagger UI /explorer · Xác thực JWKS · Basic → Identity
Package ComponentsSignal · Payment · Commerce · Finance · Inventory · Search · Asset
ServiceBusiness ServicesLogic nghiệp vụ · Validation · Điều phối
IdentityNetworkServicesignIn() HTTP → Identity service · Ủy quyền xác thực Basic liên dịch vụ
Event HandlersKafka consumer (liên service) · EventEmitter in-process (commerce/helpdesk) · IEventBus/RedisPubSubAdapter legacy/không dùng
Queue ConsumersBullMQ - 4 hệ thống · 8 loại · 3 phân vùng · Commerce · Finance · Inventory · Sale
BaseSocketEventServicebroadcast() · sendToRoom() · sendToClient() · Phân phối liên instance qua Redis
RepositorySoftDeletableRepositoryXóa mềm · Khôi phục · Bộ lọc mặc định deletedAt IS NULL tự động áp dụng
DefaultCRUDRepositoryfind · create · updateById · deleteById · count · withTransaction
InfrastructurePostgresCoreDataSourceDrizzle ORM · node-postgres Pool · 14 schema · 151 model
RedisConnectionFactoryCache · Pub/Sub · WebSocket · Chế độ Single · Chế độ Cluster
BullMQScheduler · Confirmation · Processing · 12 hàng đợi với định tuyến phân vùng hash
LớpLớp Cơ sở IGNISTrách nhiệm
ApplicationBaseApplicationQuản lý vòng đời, thiết lập middleware, gốc DI container
ComponentBaseComponentĐăng ký module tính năng (repository, service, controller)
ServiceBaseServiceLogic nghiệp vụ, điều phối giao dịch, giao tiếp bên ngoài
RepositoryDefaultCRUDRepositoryTrừu tượng truy cập dữ liệu, thao tác CRUD, xóa mềm
DataSourceBaseDataSourceCấu hình driver cơ sở dữ liệu, quản lý connection pool

3. Vòng đời Ứng dụng

3.1 Các Lớp Cơ sở Ứng dụng

@nx/core định nghĩa một lớp cơ sở trừu tượng, BaseApplication (lớp này mở rộng IGNIS BaseApplication), cùng ba lớp con cụ thể. Mỗi dịch vụ chọn một lớp con dựa trên vai trò của nó trong chuỗi tin cậy JWT.

Lớp cơ sởĐược kế thừa bởiVai trò
BaseApplication (trừu tượng)-CORS, body-limit, Swagger UI, health check, IdentityNetworkService dùng chung, luồng preConfigure(), và điều phối configureSecurity()
IssuerApplicationchỉ @nx/identityKý JWT (JWKS issuer) và phục vụ tập khóa công khai tại /jw-certs
VerifierApplication13 dịch vụ còn lạiXác minh JWT dựa trên endpoint JWKS của identity
DefaultApplicationkhông có gì (legacy)Xác thực JWS đối xứng, không có phân quyền; đã được thay thế bởi cặp Issuer/Verifier và chỉ giữ lại để tham khảo

Lớp trừu tượng BaseApplication điều khiển khởi tạo qua preConfigure(). Ở chế độ chạy MIGRATE, nó dừng sau datasource và repository; ngược lại tiếp tục qua service, component, security, và controller.

typescript
export abstract class BaseApplication extends IgnisBaseApplication {
  protected applicationRoles: string[] = [];

  protected abstract configureAuthentication(): ValueOrPromise<void>;
  protected abstract configureAuthorization(): ValueOrPromise<void>;

  preConfigure() {
    this.applicationRoles = this.getApplicationRoles();

    this.configureDatasources();
    this.configureRepositories();

    if (this.getApplicationRunMode() !== ApplicationRunModes.MIGRATE) {
      this.configureServices();
      this.configureComponents();
      this.configureSecurity(); // -> configureAuthentication() + configureAuthorization()
      this.configureControllers();
    }
  }
}

3.2 Trình tự Vòng đời

Sơ đồ sau đây cho thấy toàn bộ trình tự khởi động, từ điểm truy cập (index.ts) tới server HTTP đang chạy.

3.3 Thứ tự Phương thức preConfigure()

Thứ tự gọi phương thức bên trong preConfigure() là quan trọng. Mỗi bước phụ thuộc vào bước trước đã hoàn thành.

Thứ tựPhương thứcChức năng
1configureDatasources()Đăng ký pool kết nối PostgreSQL (mặc định không làm gì, datasource tự động phát hiện từ glob)
2configureRepositories()Đăng ký các lớp repository vào DI container (mặc định không làm gì, repository tự động phát hiện từ glob)
3configureServices()Đăng ký IdentityNetworkService cho xác thực liên dịch vụ
4configureComponents()Bind HealthCheckComponent tại /healthSwaggerComponent tại /doc
5configureSecurity()Cấu hình chiến lược xác thực JWT và Basic thông qua AuthenticateComponent
6configureControllers()Đăng ký HTTP controller (mặc định không làm gì, được ghi đè theo từng gói)

3.4 Thiết lập Middleware

setupMiddlewares() cấu hình hai middleware Hono toàn cục:

MiddlewareCấu hình
CORSOrigin: *, tất cả phương thức, 86400s max-age, credentials được bật
Body LimitTối đa 100 MB, trả về 413 Content Too Large khi vượt quá

3.5 Ghi đè trong Các Gói Downstream

Mỗi dịch vụ backend khai báo lớp Application riêng mở rộng VerifierApplication (hoặc IssuerApplication cho @nx/identity) và ghi đè các phương thức configure* tương ứng, luôn gọi super trước:

typescript
// packages/sale/src/application.ts
export class Application extends VerifierApplication {
  override configureDatasources(): void {
    super.configureDatasources();
    this.dataSource(PostgresCoreDataSource);
  }

  override configureRepositories(): void {
    super.configureRepositories();
    this.repository(SaleOrderRepository);
    this.repository(SaleOrderItemRepository);
  }

  override configureServices(): void {
    super.configureServices(); // IdentityNetworkService
    this.service(SaleOrderService);
    this.service(CheckoutService);
  }

  override async postConfigure(): Promise<void> {
    await super.postConfigure();
    // Package-specific post-boot logic
  }
}

4. Dependency Injection

DI container của IGNIS sử dụng constructor injection với decorator @inject(). Các phụ thuộc được xác định bằng khóa binding dựa trên chuỗi.

4.1 Mẫu Injection

typescript
import { inject, BaseService } from '@venizia/ignis';

export class SaleOrderService extends BaseService {
  constructor(
    @inject({ key: 'repositories.SaleOrderRepository' })
    private saleOrderRepository: SaleOrderRepository,

    @inject({ key: 'repositories.SaleOrderItemRepository' })
    private saleOrderItemRepository: SaleOrderItemRepository,
  ) {
    super({ scope: SaleOrderService.name });
  }
}

4.2 Quy ước Khóa Binding

Khóa binding tuân theo mẫu {namespace}.{ClassName}:

NamespaceKhóa Ví dụĐăng ký Thông qua
repositoriesrepositories.SaleOrderRepositorythis.application.repository(SaleOrderRepository)
servicesservices.IdentityNetworkServicethis.application.service(IdentityNetworkService)
controllerscontrollers.SaleOrderControllerthis.application.controller(SaleOrderController)
datasourcesdatasources.PostgresCoreDataSourcethis.application.datasource(PostgresCoreDataSource)

Bạn cũng có thể xây dựng khóa tường minh sử dụng tiện ích BindingKeys của IGNIS:

typescript
import { BindingKeys, BindingNamespaces } from '@venizia/ignis';

const key = BindingKeys.build({
  namespace: BindingNamespaces.REPOSITORY,
  key: 'SaleOrderRepository',
});
// Result: 'repositories.SaleOrderRepository'

4.3 Value Binding

Đối với các đối tượng cấu hình, sử dụng mẫu bind().toValue():

typescript
this.bind<IHealthCheckOptions>({
  key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,
}).toValue({
  restOptions: { path: '/health' },
});

5. Mẫu Component

Component là cơ chế chính để tổ chức các module tính năng. Mỗi component mở rộng BaseComponent và đăng ký các repository, service, và controller trong phương thức vòng đời binding().

typescript
export class ApplicationSaleComponent extends BaseComponent {
  constructor(
    @inject({ key: CoreBindings.APPLICATION_INSTANCE })
    protected application: BaseApplication,
  ) {
    super({
      scope: ApplicationSaleComponent.name,
      initDefault: { enable: true, container: application },
      bindings: {},
    });
  }

  override async binding(): Promise<void> {
    this.application.repository(SaleOrderRepository);
    this.application.repository(SaleOrderItemRepository);

    this.application.service(SaleOrderService);
    this.application.service(CheckoutService);

    this.application.controller(SaleOrderController);
  }
}

Component được đăng ký vào ứng dụng thông qua:

typescript
this.component(ApplicationSaleComponent);

5.1 Tổ hợp Component

Component có thể tải các component khác, tạo cây tổ hợp:

6. Mẫu Controller

6.1 ControllerFactory (CRUD Tự động)

IGNIS ControllerFactory tạo ra đầy đủ các endpoint CRUD từ một khai báo duy nhất. Đây là mẫu chuẩn cho hầu hết các controller trong BANA.

typescript
import { controller, inject, ControllerFactory } from '@venizia/ignis';

@controller({ path: '/sale-orders' })
export class SaleOrderController extends ControllerFactory.defineCrudController({
  repository: { name: SaleOrderRepository.name },
  authenticate: { strategies: ['jwt', 'basic'] },
  controller: { name: 'SaleOrderController', basePath: '/sale-orders' },
  entity: () => SaleOrderEntity,
}) {
  constructor(
    @inject({ key: 'repositories.SaleOrderRepository' })
    repository: SaleOrderRepository,
  ) {
    super(repository);
  }
}

Factory tạo ra các endpoint sau:

Phương thứcĐường dẫnMô tả
GET/sale-ordersDanh sách với bộ lọc, phân trang, sắp xếp
GET/sale-orders/:idTìm theo ID
GET/sale-orders/countĐếm theo bộ lọc
POST/sale-ordersTạo mới
PUT/sale-orders/:idCập nhật theo ID
DELETE/sale-orders/:idXóa theo ID (xóa mềm)

6.2 Endpoint Controller Tùy chỉnh

Các endpoint bổ sung được định nghĩa cùng với các endpoint do factory tạo bằng cách thêm phương thức vào lớp controller. Hệ thống Bộ lọc của IGNIS có sẵn trên tất cả endpoint list/count.

7. Repository và SoftDeletableRepository

7.1 Khai báo Repository

Repository được khai báo với decorator @repository, liên kết model với datasource:

typescript
import { repository } from '@venizia/ignis';
import { PostgresCoreDataSource } from '@nx/core';

@repository({ dataSource: PostgresCoreDataSource, model: SaleOrderEntity })
export class SaleOrderRepository extends SoftDeletableRepository<
  TSaleOrderSchema,
  TSaleOrder,
  TSaleOrderPersist
> {}

7.2 SoftDeletableRepository

Tất cả repository BANA đều mở rộng SoftDeletableRepository thay vì DefaultCRUDRepository. Điều này đảm bảo rằng các thao tác DELETE đặt dấu thời gian deletedAt thay vì xóa vật lý các dòng.

Phương thứcHành vi
deleteById(id)Đặt deletedAt = NOW() thay vì DELETE FROM
restoreById(id)Đặt deletedAt = NULL để khôi phục xóa mềm
find(filter)Tự động loại trừ các dòng có deletedAt IS NOT NULL

7.3 Giao dịch Cơ sở Dữ liệu

Repository cung cấp datasource để hỗ trợ giao dịch:

typescript
await this.repository.dataSource.withTransaction(async (tx) => {
  await this.saleOrderRepository.create({ data: orderData, options: { transaction: tx } });
  await this.saleOrderItemRepository.create({ data: itemData, options: { transaction: tx } });
});

7.4 PostgresCoreDataSource

Datasource dùng chung sử dụng node-postgres với Drizzle ORM. Nó tự động phát hiện model từ các binding @repository thông qua getSchema():

typescript
@datasource({ driver: 'node-postgres' })
export class PostgresCoreDataSource extends BaseDataSource<IPostgresDataSourceSettings> {
  override configure(): void {
    const schema = this.getSchema(); // Auto-discovers @repository models
    this.pool = new Pool(this.settings);
    this.connector = drizzle({ client: this.pool, schema });
  }
}

Tất cả gói backend đều re-export PostgresCoreDataSource từ datasources/index.ts cục bộ, để repository luôn tham chiếu tới cùng datasource dùng chung.

8. Eventing

Sự kiện ứng dụng liên service chạy trên Kafka (nx.bana.evt.* / nx.bana.cmd.*) và Debezium CDC (nx.bana.cdc.<schema>.<Table>) - seam chuẩn, tài liệu đầy đủ ở Kiến trúc Sự kiện.

Cơ chếLà gìPhạm vi
Kafka event/commandsự kiện ứng dụng liên serviceseam liên service thật
Debezium CDCthay đổi dòng -> read-model (Typesense, projection)sao chép dữ liệu liên service
BullMQ (Redis)job async tin cậy có retrytrong một service
EventEmitter in-process (eventemitter3)tách rời nội bộ service (chỉ commerce, helpdesk)trong một service
WebSocket (Signal)đẩy real-time tới client, fan-out giữa instance qua Redisgiao tới client

Legacy / không dùng

Abstraction IEventBus + RedisPubSubAdapter và các hằng PaymentEventChannels / UserOnboardingEventChannels trong @nx/core (payment.order.success, commerce.initialized, ...) là code chết - không bao giờ được khởi tạo. Redis không phải event bus liên service (chỉ là cache + store BullMQ + fan-out WebSocket). Seam PAYMENT_SUCCESS thật là topic Kafka nx.bana.evt.payment.succeeded; onboarding merchant lan truyền qua CDC nx.bana.cdc.public.Merchant.

8.1 Sự kiện WebSocket

@nx/core cung cấp lớp tiện ích dựng room và topic WebSocket cho Signal service:

Tiện íchĐịnh dạngVí dụ
WebSocketRooms.build()wr:{prefix}/{paths}wr:observation/merchants/abc-123
WebSocketTopics.build()ws:{paths joined by .}ws:observation.sale.sale-order

9. Bootstrap Helper

@nx/core cung cấp hai hàm bootstrap chuẩn hóa điểm truy cập trên tất cả các gói. Xem tham chiếu Bootstrapping của IGNIS cho các khái niệm framework cơ sở.

9.1 Bootstrap Ứng dụng

Được sử dụng trong src/index.ts của mỗi gói để khởi động HTTP server:

typescript
// packages/sale/src/index.ts
import { bootstrapApplication } from '@nx/core';
import { Application } from './application';
import { appConfig } from './common/app-config';
import { resolve } from 'node:path';

bootstrapApplication({
  ApplicationClass: Application,
  config: appConfig,
  options: { bannerPath: resolve(__dirname, '../resources/banner.txt') },
});

Trình tự bootstrap là: new Application() --> init() --> boot() --> start().

9.2 Bootstrap Migration

Được sử dụng trong src/migrate.ts của mỗi gói để chạy seed và migration cơ sở dữ liệu:

typescript
// packages/sale/src/migrate.ts
import { bootstrapMigration } from '@nx/core';
import { Application } from './application';
import { getMigrationProcesses } from './migrations/processes/migration-process';

bootstrapMigration({
  ApplicationClass: Application,
  getMigrationProcesses,
});

9.3 createMigrationProcessLoader

Hàm factory tạo trình lấy quy trình migration từ danh sách đường dẫn file seed:

typescript
// packages/sale/src/migrations/processes/migration-process.ts
import { createMigrationProcessLoader } from '@nx/core';

export const getMigrationProcesses = createMigrationProcessLoader({
  seedPaths: [
    'sale-0001-seed-initial-data',
    'sale-0002-seed-tracking-types',
  ],
  importFn: (path) => import(`../processes/${path}.js`),
});

Mỗi quy trình migration là một đối tượng với name, migrateFn, và cleanFn tùy chọn. Lớp MigrationHelper theo dõi trạng thái thực thi trong cơ sở dữ liệu để ngăn chạy trùng lặp.

9.4 createAppConfig

Tập trung cấu hình ứng dụng để mỗi gói sử dụng cùng cấu trúc:

typescript
// packages/sale/src/common/app-config.ts
import { createAppConfig } from '@nx/core';

export const appConfig = createAppConfig();

Hàm này đọc từ biến môi trường và trả về đối tượng IApplicationConfigs với host, port, base path, cài đặt debug, và boot option (mẫu glob để tự động phát hiện datasource và repository từ @nx/core).

10. Giao tiếp Liên Dịch vụ

10.1 IdentityNetworkService

Client mạng liên dịch vụ duy nhất trong hệ thống. Nó mở rộng AxiosNetworkRequest từ @venizia/ignis-helpers/axios và giao tiếp với dịch vụ Identity để xác minh thông tin đăng nhập.

typescript
export class IdentityNetworkService extends AxiosNetworkRequest {
  constructor() {
    super({
      name: IdentityNetworkService.name,
      networkOptions: {
        baseUrl: applicationEnvironment.get<string>(
          EnvironmentKeys.APP_ENV_IDENTITY_SERVICE_BASE_URL,
        ),
      },
    });
  }

  async signIn(opts: {
    identifier: { scheme: string; value: string };
    credential: { scheme: string; value: string };
  }) {
    const networkService = this.getNetworkService();
    const response = await networkService.post({
      url: '/auth/sign-in',
      body: opts,
    });
    return response.data;
  }
}

Dịch vụ này được đăng ký mặc định trong BaseApplication.configureServices(), giúp nó có sẵn cho tất cả gói downstream để xác minh thông tin đăng nhập Basic auth.

10.2 Topology Giao tiếp

Không có API gateway. Mỗi dịch vụ tự xử lý xác thực của riêng mình và cung cấp HTTP API trực tiếp. Cuộc gọi HTTP liên dịch vụ duy nhất là để xác minh thông tin đăng nhập Basic auth.

Tất cả giao tiếp liên dịch vụ khác đều thông qua sự kiện Redis Pub/Sub hoặc hàng đợi BullMQ (xem Phần 8).

11. Luồng Xác thực

BaseApplication.configureSecurity() ủy thác cho các phương thức trừu tượng configureAuthentication()configureAuthorization(). Mỗi lớp con triển khai chúng, thiết lập IGNIS AuthenticateComponent với hai chiến lược (JWT + Basic).

11.1 Chiến lược JWT (JWKS)

JWT được ký và xác minh qua chuỗi tin cậy JWKS thay vì một secret đối xứng dùng chung:

Vai tròLớpChiến lượcHành vi
IssuerIssuerApplication (@nx/identity)JWKSIssuerAuthenticationStrategyKý token bằng khóa riêng PEM, công bố tập khóa công khai tại /jw-certs
VerifierVerifierApplication (13 dịch vụ)JWKSVerifierAuthenticationStrategyXác minh token dựa trên JWKS URL của identity (APP_ENV_IDENTITY_SERVICE_BASE_URL + /jw-certs)
Biến Môi trườngDùng bởiMục đích
APP_ENV_JWKS_ALGORITHMIssuerThuật toán ký (mặc định ES256)
APP_ENV_JWKS_PRIVATE_KEY / APP_ENV_JWKS_PUBLIC_KEYIssuerCặp khóa PEM
APP_ENV_JWKS_REST_PATHCả haiĐường dẫn endpoint JWKS (mặc định /jw-certs)
APP_ENV_IDENTITY_SERVICE_BASE_URLVerifierURL cơ sở của dịch vụ issuer (identity)
APP_ENV_JWT_EXPIRES_INIssuerThời gian hết hạn token tính bằng giây
APP_ENV_APPLICATION_SECRETCả haiSecret cấp ứng dụng

11.2 Chiến lược Basic

Ủy quyền xác minh thông tin đăng nhập cho dịch vụ Identity thông qua IdentityNetworkService.signIn():

11.3 Đăng ký Chiến lược

Mỗi lớp con đăng ký hai chiến lược của nó trong singleton AuthenticationStrategyRegistry. Một dịch vụ verifier đăng ký:

typescript
AuthenticationStrategyRegistry.getInstance().register({
  container: this,
  strategies: [
    { name: Authentication.STRATEGY_JWT, strategy: JWKSVerifierAuthenticationStrategy },
    { name: Authentication.STRATEGY_BASIC, strategy: BasicAuthenticationStrategy },
  ],
});

IssuerApplication đăng ký JWKSIssuerAuthenticationStrategy cho chiến lược JWT thay vào đó. Controller chỉ định chiến lược nào được sử dụng trong cấu hình authenticate:

typescript
authenticate: { strategies: ['jwt', 'basic'] }

12. Tiện ích Dùng chung

@nx/core cung cấp một số tiện ích singleton được sử dụng trên tất cả các gói.

Tiện íchMục đích
IdGeneratorSingleton tạo ID Snowflake (bao bọc IGNIS SnowflakeUidHelper)
CryptoUtilityMã hóa AES-256-GCM và ký HMAC sử dụng APP_ENV_APPLICATION_SECRET
useRequestContext()Trích xuất người dùng đã xác thực, vai trò, và cung cấp helper định dạng phản hồi
@logged decoratorGhi log đo lường hiệu suất cấp phương thức
RedisConnectionFactoryTạo kết nối Redis chế độ single hoặc cluster

12.1 IdGenerator

typescript
import { IdGenerator } from '@nx/core';

const id = IdGenerator.getInstance().nextId();
// Returns: '7193487234817024' (Snowflake ID string)

Cấu hình thông qua biến môi trường:

  • APP_ENV_SNOWFLAKE_WORKER_ID (0-1023, duy nhất cho mỗi instance dịch vụ)
  • APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT (epoch tùy chỉnh tính bằng mili giây)

12.2 useRequestContext()

Wrapper xung quanh useRequestContext của IGNIS bổ sung các trường đặc thù BANA:

typescript
const {
  context,        // Hono request context
  currentUser,    // JWT payload with userId, roles
  userId,         // Shortcut: currentUser.userId
  roles,          // Shortcut: currentUser.roles[].identifier
  isAlwaysAllowed, // true if user has SUPER_ADMIN or ADMIN role
  normalizeCountableData,  // Format list responses with count/range headers
  formatResponse,          // Format single-item responses
  formatArrayResponse,     // Format array responses
} = useRequestContext();

13. Chuỗi Phụ thuộc Gói

Tất cả gói backend đều phụ thuộc vào @nx/core. Sơ đồ sau đây cho thấy cây phụ thuộc đầy đủ:

GóiPhụ thuộc Trực tiếp
@nx/coreKhông (nền tảng)
@nx/asset@nx/core
@nx/search@nx/core
@nx/inventory@nx/core
@nx/identity@nx/core
@nx/finance@nx/core
@nx/signal@nx/core
@nx/payment@nx/core, @nx/mq-pay
@nx/sale@nx/core
@nx/commerce@nx/core, @nx/asset, @nx/search, @nx/inventory

14. Schema Cơ sở Dữ liệu

@nx/core định nghĩa tất cả Drizzle ORM schema tập trung để mỗi dịch vụ truy cập cùng cấu trúc cơ sở dữ liệu. Schema được tổ chức trên 14 schema PostgreSQL:

Schema PostgreSQLSố lượng ModelMiền
helpdesk30Ticket, nhân viên hỗ trợ, SLA, hội thoại
public26Người dùng, vai trò, sản phẩm, merchant, tổ chức, cấu hình
inventory17Tồn kho, đơn đặt hàng, nhà cung cấp, theo dõi
sale21Đơn hàng và sản phẩm đơn hàng
invoice9Hóa đơn điện tử, thông tin thuế
pricing9Giá, quy tắc định giá, chi phí, thuế
identity8Xác thực, quyền, chính sách
ledger8Tài khoản và bút toán kép
finance6Ví, giao dịch, danh mục
tax6Quy tắc và cấu hình thuế
licensing5Gói thuê bao và giấy phép
allocation4Chỗ ngồi sự kiện và bố cục địa điểm
outreach2Chiến dịch và nhắn tin
payment0Dự phòng (không có thực thể)

Tài liệu schema chi tiết, xem ERD Cơ sở Dữ liệu.

15. Tài liệu Liên quan

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