Bỏ qua, đến nội dung

@digiforce-nc/server

npm@digiforce-nc/server
Importimport { Application, Plugin, PluginManager, AppSupervisor } from '@digiforce-nc/server'
RuntimeNode.js

Tổng quan

@digiforce-nc/serverkernel của hệ thống backend Digiforce. Class trung tâm Application kế thừa Koa và mixin AsyncEmitter, đóng vai trò:

  • HTTP server - nhận request, chạy middleware pipeline (topological sort)
  • Event bus - phát/nhận async event qua emitAsync()
  • Orchestrator - khởi tạo và quản lý Database, PluginManager, DataSourceManager, CacheManager, AuthManager, ACL, CronManager, PubSubManager, LockManager

Mọi thành phần khác (plugin, data source, resource, middleware) đều gắn vào Application.


Class diagram


Application API

Lifecycle methods

MethodMô tả
constructor(options)Khởi tạo instance. Options gồm database config, plugins, cache, logger, i18n. Gọi init() tự động.
init()Dựng "khung" 20 bước: logger → mainDataSource → services → PluginManager → middleware → actions → CLI. Chưa load plugin.
load(options?)Nạp plugin: beforeLoadloadafterLoad. Optional sync DB.
start(options?)Emit beforeStartstart() HTTP listener → emit afterStart.
stop(options?)Emit beforeStop → đóng tất cả data source → cleanup → emit afterStop.
install(options?)First-time setup: load() → sync DB → chạy plugin.install() cho mỗi plugin → emit afterInstall.
upgrade(options?)Upgrade: reInit → load → sync → chạy migration cho mỗi plugin.
reload()Hot reload: dispose service cũ → init()load(). Không tắt HTTP listener.
restart()Full restart: stop()start(). Dùng khi config thay đổi lớn.

reload vs restart

  • reload() - dev mode, giữ HTTP listener, nhanh
  • restart() - production, tắt hoàn toàn rồi bật lại

Utility methods

MethodMô tả
use(middleware, options?)Đăng ký middleware vào Toposort. Options: tag, before, after, group.
command(name, options?)Đăng ký CLI command (qua commander).
getVersion()Trả về version hiện tại của application + installed plugins.
runAsCLI(argv?)Khởi chạy app ở chế độ CLI (parse argv, chạy command tương ứng).

Property accessors

Application cung cấp shortcut getter tới các service qua MainDataSource:

PropertyKiểuNguồn
app.dbDatabasemainDataSource.collectionManager.db
app.aclACLmainDataSource.acl
app.resourceManagerResourceManagermainDataSource.resourceManager
app.dataSourceManagerDataSourceManagerTrực tiếp trên Application
app.authManagerAuthManagerTrực tiếp trên Application
app.cacheManagerCacheManagerTrực tiếp trên Application
app.lockManagerLockManagerTrực tiếp trên Application
app.cronManagerCronManagerTrực tiếp trên Application
app.pubSubManagerPubSubManagerTrực tiếp trên Application

Deprecated APIs

Thay bằng
app.resourcerapp.resourceManager
app.collection(...)app.db.collection(...)
app.resource(...)app.resourceManager.define(...)
app.actions(...)app.resourceManager.registerActionHandler(...)

Plugin class

Mỗi plugin kế thừa class Plugin và override lifecycle hooks:

Lifecycle hooks

HookKhi nàoMục đích
afterAdd()Ngay sau khi plugin được add vào PluginManagerĐăng ký resource sớm, dependency check
beforeLoad()Vòng 1 - trước khi load bất kỳ plugin nàoSetup global state, pre-configure collection
load()Vòng 2 - sau khi tất cả plugin đã beforeLoadĐăng ký collection, resource, middleware, action
install(options?)First-time installSeed data, tạo bảng, cấu hình mặc định
enable()Khi plugin được bậtActivate logic
disable()Khi plugin bị tắtDeactivate logic
afterEnable()Sau enable thành côngPost-enable cleanup
afterDisable()Sau disable thành côngPost-disable cleanup
afterRemove()Khi plugin bị gỡ khỏi hệ thốngXóa data, cleanup hoàn toàn

Ví dụ plugin cơ bản

typescript
import { Plugin } from '@digiforce-nc/server';

export class MyPlugin extends Plugin {
  async beforeLoad() {
    // Đăng ký collection trước khi load
    this.app.db.collection({
      name: 'tasks',
      fields: [
        { type: 'string', name: 'title' },
        { type: 'boolean', name: 'completed', defaultValue: false },
        { type: 'date', name: 'dueDate' },
      ],
    });
  }

  async load() {
    // Đăng ký custom action
    this.app.resourceManager.registerActionHandler('tasks:complete', async (ctx, next) => {
      const { filterByTk } = ctx.action.params;
      await ctx.db.getRepository('tasks').update({
        filterByTk,
        values: { completed: true },
      });
      ctx.body = { ok: true };
      await next();
    });

    // Đăng ký middleware
    this.app.acl.allow('tasks', 'list', 'loggedIn');
  }

  async install() {
    // Seed dữ liệu mặc định
    await this.app.db.getRepository('tasks').create({
      values: { title: 'Welcome task', completed: false },
    });
  }
}

PluginManager API

PluginManager quản lý lifecycle của tất cả plugin trong Application.

MethodMô tả
add(plugin, options?)Thêm plugin vào danh sách. Gọi plugin.afterAdd().
get(name)Lấy plugin instance theo tên.
enable(name)Bật plugin: gọi plugin.enable()plugin.afterEnable().
disable(name)Tắt plugin: gọi plugin.disable()plugin.afterDisable().
install(options?)Chạy plugin.install() cho tất cả plugin cần install.
remove(name)Gỡ plugin: gọi plugin.afterRemove() → xóa khỏi map.
load(options?)Load tất cả plugin: vòng 1 beforeLoad → vòng 2 load.

Tại sao load 2 vòng?

Vòng 1: A.beforeLoad() → B.beforeLoad() → C.beforeLoad()
Vòng 2: A.load()       → B.load()       → C.load()

Plugin B có thể cần metadata từ plugin A. Tách 2 vòng đảm bảo tất cả plugin đã beforeLoad() trước khi bất kỳ plugin nào load().


AppSupervisor

AppSupervisorsingleton quản lý nhiều instance Application trong cùng process.

MethodMô tả
getInstance()Trả về singleton instance.
addApp(app)Đăng ký application. Emit afterAppAdded.
removeApp(name)Gỡ application khỏi supervisor.
getApp(name)Lấy app instance theo tên.
getApps()Lấy tất cả app instances.

Multi-tenant

Trong triển khai multi-tenant, mỗi tenant có thể có một Application riêng. AppSupervisor giúp quản lý tất cả từ một process duy nhất.


Event catalog

Application emit nhiều event trong suốt lifecycle. Plugin lắng nghe các event này để hook vào đúng thời điểm.

EventKhi nàoThường dùng cho
beforeLoadTrước khi load tất cả pluginPre-configure, validate
afterLoadSau khi load tất cả pluginPost-configure, dependency check
beforeStartTrước khi app listen HTTPWarm cache, check connection
afterStartApp đã listenLog, bật cron job
beforeStopTrước khi shutdownCleanup, flush buffer
afterStopĐã shutdown xongFinal log
beforeInstallTrước khi install lần đầuValidate environment
afterInstallSau khi install xongPost-setup action
beforeUpgradeTrước khi upgradeBackup preparation
afterUpgradeSau khi upgradeMigration verification
beforeReloadTrước khi reloadSnapshot state
afterReloadSau khi reload xongRestore state
beforeLoadPluginTrước load từng pluginPer-plugin pre-processing
afterLoadPluginSau load từng pluginReact khi plugin cụ thể load xong
beforeAddDataSourceTrước khi add data sourceSetup hooks cho data source mới
afterAddDataSourceSau khi add data sourceSync ACL, register resources
maintainingApp đang ở chế độ maintenanceHiển thị maintenance page
errorLỗi không xử lý đượcLog error, alert

Sử dụng event

typescript
app.on('afterStart', async () => {
  console.log(`Server started on port ${app.options.port}`);
});

app.on('beforeStop', async () => {
  await flushMetrics();
});

Ví dụ sử dụng

Khởi tạo Application cơ bản

typescript
import { Application } from '@digiforce-nc/server';

const app = new Application({
  database: {
    dialect: 'postgres',
    host: 'localhost',
    port: 5432,
    database: 'my_app',
    username: 'admin',
    password: 'secret',
  },
  plugins: ['plugin-users', 'plugin-acl', 'plugin-ui-schema-storage'],
});

// CLI mode
app.runAsCLI();

Đăng ký middleware với Toposort

typescript
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  ctx.set('X-Response-Time', `${Date.now() - start}ms`);
}, {
  tag: 'responseTime',
  before: 'dataSource',
});

Dependencies

@digiforce-nc/server phụ thuộc trực tiếp vào các core package sau:

PackageVai trò
@digiforce-nc/databaseORM layer (Database, Collection, Repository)
@digiforce-nc/resourcerResource routing (ResourceManager, Resource, Action)
@digiforce-nc/data-source-managerMulti data source orchestration
@digiforce-nc/aclAccess control list engine
@digiforce-nc/authAuthentication manager
@digiforce-nc/cacheCache manager
@digiforce-nc/loggerLogging
@digiforce-nc/telemetryObservability (OpenTelemetry)

Xem thêm