Giao diện
@digiforce-nc/server
| npm | @digiforce-nc/server |
| Import | import { Application, Plugin, PluginManager, AppSupervisor } from '@digiforce-nc/server' |
| Runtime | Node.js |
Tổng quan
@digiforce-nc/server là kernel 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
| Method | Mô 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: beforeLoad → load → afterLoad. Optional sync DB. |
start(options?) | Emit beforeStart → start() 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, nhanhrestart()- production, tắt hoàn toàn rồi bật lại
Utility methods
| Method | Mô 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:
| Property | Kiểu | Nguồn |
|---|---|---|
app.db | Database | mainDataSource.collectionManager.db |
app.acl | ACL | mainDataSource.acl |
app.resourceManager | ResourceManager | mainDataSource.resourceManager |
app.dataSourceManager | DataSourceManager | Trực tiếp trên Application |
app.authManager | AuthManager | Trực tiếp trên Application |
app.cacheManager | CacheManager | Trực tiếp trên Application |
app.lockManager | LockManager | Trực tiếp trên Application |
app.cronManager | CronManager | Trực tiếp trên Application |
app.pubSubManager | PubSubManager | Trực tiếp trên Application |
Deprecated APIs
| Cũ | Thay bằng |
|---|---|
app.resourcer | app.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
| Hook | Khi nào | Mụ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ào | Setup 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 install | Seed data, tạo bảng, cấu hình mặc định |
enable() | Khi plugin được bật | Activate logic |
disable() | Khi plugin bị tắt | Deactivate logic |
afterEnable() | Sau enable thành công | Post-enable cleanup |
afterDisable() | Sau disable thành công | Post-disable cleanup |
afterRemove() | Khi plugin bị gỡ khỏi hệ thống | Xó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.
| Method | Mô 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
AppSupervisor là singleton quản lý nhiều instance Application trong cùng process.
| Method | Mô 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.
| Event | Khi nào | Thường dùng cho |
|---|---|---|
beforeLoad | Trước khi load tất cả plugin | Pre-configure, validate |
afterLoad | Sau khi load tất cả plugin | Post-configure, dependency check |
beforeStart | Trước khi app listen HTTP | Warm cache, check connection |
afterStart | App đã listen | Log, bật cron job |
beforeStop | Trước khi shutdown | Cleanup, flush buffer |
afterStop | Đã shutdown xong | Final log |
beforeInstall | Trước khi install lần đầu | Validate environment |
afterInstall | Sau khi install xong | Post-setup action |
beforeUpgrade | Trước khi upgrade | Backup preparation |
afterUpgrade | Sau khi upgrade | Migration verification |
beforeReload | Trước khi reload | Snapshot state |
afterReload | Sau khi reload xong | Restore state |
beforeLoadPlugin | Trước load từng plugin | Per-plugin pre-processing |
afterLoadPlugin | Sau load từng plugin | React khi plugin cụ thể load xong |
beforeAddDataSource | Trước khi add data source | Setup hooks cho data source mới |
afterAddDataSource | Sau khi add data source | Sync ACL, register resources |
maintaining | App đang ở chế độ maintenance | Hiển thị maintenance page |
error | Lỗi không xử lý được | Log 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:
| Package | Vai trò |
|---|---|
@digiforce-nc/database | ORM layer (Database, Collection, Repository) |
@digiforce-nc/resourcer | Resource routing (ResourceManager, Resource, Action) |
@digiforce-nc/data-source-manager | Multi data source orchestration |
@digiforce-nc/acl | Access control list engine |
@digiforce-nc/auth | Authentication manager |
@digiforce-nc/cache | Cache manager |
@digiforce-nc/logger | Logging |
@digiforce-nc/telemetry | Observability (OpenTelemetry) |
Xem thêm
- Server Application - phân tích code-level chi tiết
init(),load(),start(), events - Server Architecture - kiến trúc tổng thể backend
- FAQ - câu hỏi thường gặp
- Mã nguồn