Giao diện
@digiforce-nc/sdk
| Package | @digiforce-nc/sdk |
| Depends on | axios, qs (không phụ thuộc core package nào) |
1) Tổng quan
@digiforce-nc/sdk là client SDK để giao tiếp với Digiforce server API từ browser hoặc Node.js. Cung cấp APIClient cho HTTP communication, storage adapters cho token persistence, và Auth utilities cho xác thực.
2) APIClient API
Constructor
typescript
import { APIClient } from '@digiforce-nc/sdk';
const api = new APIClient({
baseURL: 'http://localhost:13000/api',
headers: {
'X-App': 'my-app',
},
storageType: 'localStorage', // 'localStorage' | 'sessionStorage' | 'memory'
});| Option | Kiểu | Mô tả |
|---|---|---|
baseURL | string | URL gốc của API server |
headers | object | Headers mặc định cho mọi request |
storageType | string | Loại storage cho token persistence |
request(config)
Gửi HTTP request (wrapper quanh axios):
typescript
// GET request
const response = await api.request({
url: 'users:list',
method: 'GET',
params: {
pageSize: 20,
page: 1,
filter: { status: 'active' },
},
});
// POST request
const result = await api.request({
url: 'users:create',
method: 'POST',
data: {
username: 'john',
email: 'john@example.com',
},
});resource(name)
Tạo Resource instance cho CRUD operations:
typescript
const usersResource = api.resource('users');
const postsResource = api.resource('posts');axios
Truy cập trực tiếp axios instance bên dưới:
typescript
api.axios.defaults.timeout = 5000;interceptors
Đăng ký request/response interceptors:
typescript
api.axios.interceptors.request.use((config) => {
config.headers['X-Request-Id'] = generateId();
return config;
});
api.axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
redirectToLogin();
}
return Promise.reject(error);
},
);3) Resource API
Resource cung cấp CRUD interface thống nhất, map trực tiếp với server-side actions:
list(params)
typescript
const { data } = await api.resource('users').list({
pageSize: 20,
page: 1,
sort: ['-createdAt'],
filter: {
status: { $eq: 'active' },
},
fields: ['id', 'username', 'email'],
appends: ['roles'],
});
// data = { data: [...], meta: { count, page, pageSize, totalPage } }get(params)
typescript
const { data } = await api.resource('users').get({
filterByTk: 1,
fields: ['id', 'username', 'email', 'profile'],
appends: ['roles', 'departments'],
});create(params)
typescript
const { data } = await api.resource('users').create({
values: {
username: 'jane',
email: 'jane@example.com',
roles: [{ id: 1 }],
},
});update(params)
typescript
await api.resource('users').update({
filterByTk: 1,
values: {
email: 'new-email@example.com',
},
});destroy(params)
typescript
await api.resource('users').destroy({
filterByTk: 1,
});
// Bulk delete
await api.resource('users').destroy({
filter: { status: 'inactive' },
});4) ActionParams type
Mọi resource action nhận ActionParams:
typescript
interface ActionParams {
resource?: string; // Tên resource
action?: string; // Tên action
params?: Record<string, any>; // Query parameters / request body
}Custom actions:
typescript
// Gọi custom action
await api.resource('users').call('activate', {
filterByTk: 1,
values: { reason: 'approved by admin' },
});
// Tương đương
await api.request({
url: 'users:activate/1',
method: 'POST',
data: { reason: 'approved by admin' },
});5) Auth class
Token management
typescript
// Sign in - nhận và lưu token
await api.auth.signIn({
email: 'admin@example.com',
password: 'secret',
});
// Token tự động được attach vào mọi request sau khi sign in
console.log(api.auth.getToken()); // 'eyJhbGciOi...'
// Sign out - xóa token
await api.auth.signOut();Flow xác thực
6) Storage adapters
BaseStorage interface
typescript
interface BaseStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
}Adapters có sẵn
| Adapter | Persistence | Phạm vi | Phù hợp cho |
|---|---|---|---|
| LocalStorage | Vĩnh viễn (đến khi xóa) | Cùng origin | Web app thông thường |
| SessionStorage | Đến khi đóng tab | Cùng tab | Session ngắn, bảo mật cao hơn |
| MemoryStorage | Đến khi refresh | Cùng runtime | Node.js, SSR, testing |
typescript
// Dùng MemoryStorage cho Node.js
import { APIClient, MemoryStorage } from '@digiforce-nc/sdk';
const api = new APIClient({
baseURL: 'http://localhost:13000/api',
storageType: 'memory',
});Node.js
Trong môi trường Node.js (không có window), SDK tự động fallback sang MemoryStorage. Không cần cấu hình thêm.
7) getSubAppName()
Resolve tên sub-application từ URL path hoặc headers:
typescript
import { getSubAppName } from '@digiforce-nc/sdk';
const subApp = getSubAppName();
// Đọc từ URL path: /apps/my-tenant/... → 'my-tenant'
// Hoặc từ header: X-App → giá trị headerHữu ích trong multi-tenant setup nơi mỗi tenant chạy sub-application riêng.
8) Code example đầy đủ
typescript
import { APIClient } from '@digiforce-nc/sdk';
// Khởi tạo
const api = new APIClient({
baseURL: 'https://app.digiforce.vn/api',
});
// Đăng nhập
await api.auth.signIn({
email: 'admin@company.com',
password: 'secure-password',
});
// CRUD operations
const { data: users } = await api.resource('users').list({
page: 1,
pageSize: 10,
filter: { 'roles.name': { $includes: 'admin' } },
appends: ['roles', 'departments'],
sort: ['-createdAt'],
});
console.log(`Tìm thấy ${users.meta.count} users`);
for (const user of users.data) {
console.log(`${user.username} - ${user.roles.map(r => r.name).join(', ')}`);
}
// Tạo record mới
const { data: newOrder } = await api.resource('orders').create({
values: {
customerId: 42,
items: [
{ productId: 1, quantity: 2 },
{ productId: 5, quantity: 1 },
],
status: 'pending',
},
});
console.log(`Đơn hàng ${newOrder.data.id} đã được tạo`);
// Đăng xuất
await api.auth.signOut();CORS
Khi gọi API từ browser khác domain, đảm bảo server đã cấu hình CORS cho phép origin của client. Xem cấu hình CORS_ORIGIN trong Server Application.