@arda-labs/core
v0.1.2
Published
Core Angular library for Arda Multi-tenant Platform - Essential guards, interceptors, services, and PrimeNG re-exports for micro-frontends
Maintainers
Readme
@arda-labs/core
Shared Angular library for Arda Multi-tenant Platform. Provides reusable guards, interceptors, services, directives, pipes, and PrimeNG component re-exports for micro-frontend applications.
📦 Installation
npm install @arda-labs/corePeer Dependencies
This library requires the following peer dependencies:
{
"@angular/common": "^21.0.0",
"@angular/core": "^21.0.0",
"@angular/router": "^21.0.0",
"@angular/platform-browser": "^21.0.0",
"@primeuix/themes": "^2.0.2",
"primeng": "^21.0.0",
"rxjs": "~7.8.0"
}Import Usage
import { AuthService, authGuard, provideArdaShared } from '@arda-labs/core';🎯 Tính năng chính
1. HTTP Interceptors
Tự động xử lý các request/response HTTP:
Auth Interceptor
- Tự động gắn JWT token vào header
Authorization: Bearer {token} - Skip cho public endpoints
// Tự động apply khi dùng provideArdaShared()
// Request sẽ có header: Authorization: Bearer eyJhbGc...Tenant Interceptor
- Tự động gắn tenant code vào header
X-Tenant-Code - Backend sử dụng header này để routing đến đúng database
// Tự động apply
// Request sẽ có header: X-Tenant-Code: vinamilkError Interceptor
- Xử lý lỗi HTTP toàn cục
- Hiển thị toast notification
- Redirect khi 401 Unauthorized
// Tự động hiển thị toast khi có lỗi HTTP
// 401 -> redirect to /tenant-select
// 403 -> "Bạn không có quyền..."
// 404 -> "Không tìm thấy tài nguyên"Loading Interceptor
- Tự động hiển thị loading indicator
- Đếm số lượng requests đang chạy
// Skip loading cho một request cụ thể
this.http.get(url, {
headers: new HttpHeaders({ 'X-Skip-Loading': 'true' })
});2. Authentication
AuthService
Quản lý authentication với Keycloak:
import { AuthService } from 'shared';
constructor(private authService: AuthService) {}
// Login
this.authService.login({
username: '[email protected]',
password: 'password',
tenantCode: 'vinamilk'
}).subscribe(response => {
console.log('Logged in:', response.user);
});
// Logout
this.authService.logout();
// Check authentication
if (this.authService.isAuthenticated()) {
// User is authenticated
}
// Check roles
if (this.authService.hasRole('ADMIN')) {
// User is admin
}
if (this.authService.hasAnyRole(['ADMIN', 'MANAGER'])) {
// User is admin or manager
}TokenService
Quản lý JWT tokens:
import { TokenService } from 'shared';
constructor(private tokenService: TokenService) {}
// Get token
const token = this.tokenService.getToken();
// Check if expired
if (this.tokenService.isTokenExpired()) {
// Token expired
}
// Get user info from token
const user = this.tokenService.getUserFromToken();3. Guards
Auth Guard
Bảo vệ routes yêu cầu authentication:
import { authGuard } from 'shared';
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [authGuard]
}
];Tenant Guard
Kiểm tra tenant đã được chọn:
import { tenantGuard } from 'shared';
const routes: Routes = [
{
path: 'app',
canActivate: [tenantGuard],
children: [...]
}
];Role Guard
Bảo vệ routes theo role:
import { roleGuard } from 'shared';
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [roleGuard(['ADMIN'])]
},
{
path: 'management',
component: ManagementComponent,
canActivate: [roleGuard(['ADMIN', 'MANAGER'])]
}
];4. UI Services
ToastService
Hiển thị thông báo toast (wrapper cho PrimeNG MessageService):
import { ToastService } from 'shared';
constructor(private toastService: ToastService) {}
// Success
this.toastService.showSuccess('Thành công', 'Dữ liệu đã được lưu');
// Error
this.toastService.showError('Lỗi', 'Không thể kết nối server');
// Warning
this.toastService.showWarning('Cảnh báo', 'Dữ liệu chưa đầy đủ');
// Info
this.toastService.showInfo('Thông tin', 'Hệ thống sẽ bảo trì lúc 2h sáng');LoadingService
Quản lý loading state toàn cục:
import { LoadingService } from 'shared';
constructor(private loadingService: LoadingService) {}
// Show loading
this.loadingService.show();
// Hide loading
this.loadingService.hide();
// Check loading state (Signal)
console.log(this.loadingService.isLoading());
// Force hide (reset count)
this.loadingService.forceHide();5. Storage Service
Wrapper an toàn cho localStorage/sessionStorage:
import { StorageService } from 'shared';
constructor(private storage: StorageService) {}
// LocalStorage
this.storage.setLocal('user', { name: 'John' });
const user = this.storage.getLocal<User>('user');
this.storage.removeLocal('user');
// SessionStorage
this.storage.setSession('tempData', data);
const tempData = this.storage.getSession('tempData');
// Check existence
if (this.storage.hasLocal('token')) {
// Token exists
}6. Logger Service
Logging với level control:
import { LoggerService, LogLevel } from 'shared';
constructor(private logger: LoggerService) {
// Set log level (production: ERROR only)
this.logger.setLogLevel(LogLevel.ERROR);
}
// Different log levels
this.logger.debug('Debug message', data);
this.logger.info('Info message', data);
this.logger.warn('Warning message', data);
this.logger.error('Error occurred', error);
// HTTP logging
this.logger.logRequest('POST', '/api/users', body);
this.logger.logResponse('POST', '/api/users', 201, response);7. Directives
Permission Directive
Hiển thị/ẩn element dựa trên role:
<!-- Single role -->
<button *appPermission="'ADMIN'">Admin Only</button>
<!-- Multiple roles -->
<div *appPermission="['ADMIN', 'MANAGER']">
Admin or Manager content
</div>Debounce Directive
Delay event firing:
<input
type="text"
(input)="onSearch($event)"
appDebounce
[debounceTime]="500"
(debounceEvent)="onDebouncedSearch($event)"
/>AutoFocus Directive
Tự động focus vào element:
<!-- Always focus -->
<input appAutoFocus />
<!-- Conditional focus -->
<input appAutoFocus [autoFocus]="shouldFocus" />8. Pipes
SafeHtml Pipe
Sanitize HTML content:
<div [innerHTML]="htmlContent | safeHtml"></div>Truncate Pipe
Cắt chuỗi và thêm ...:
<!-- Truncate to 50 chars -->
{{ longText | truncate }}
<!-- Custom length -->
{{ longText | truncate:100 }}
<!-- Custom trail -->
{{ longText | truncate:100:'[...]' }}9. Models & Interfaces
API Response
import { ApiResponse, PaginationResponse } from 'shared';
interface User {
id: string;
name: string;
}
// Single item response
const response: ApiResponse<User> = {
success: true,
data: { id: '1', name: 'John' }
};
// Paginated response
const paginatedResponse: PaginationResponse<User> = {
content: [...],
totalElements: 100,
totalPages: 10,
size: 10,
number: 0,
first: true,
last: false
};Common Models
import { SelectOption, TableColumn, BreadcrumbItem } from 'shared';
// Select options
const options: SelectOption[] = [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2', disabled: true }
];
// Table columns
const columns: TableColumn[] = [
{ field: 'name', header: 'Name', sortable: true },
{ field: 'email', header: 'Email', filterable: true },
{ field: 'age', header: 'Age', type: 'number', align: 'right' }
];
// Breadcrumbs
const breadcrumbs: BreadcrumbItem[] = [
{ label: 'Home', url: '/' },
{ label: 'Users', url: '/users' },
{ label: 'Profile' }
];⚙️ Setup
1. Import in app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { providePrimeNG } from 'primeng/config';
import { provideArdaShared, ArdaPreset, API_CONFIG } from '@arda-labs/core';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideAnimationsAsync(),
providePrimeNG({
theme: {
preset: ArdaPreset
}
}),
// Provide all shared services and interceptors
provideArdaShared(),
// Configure API endpoints
{
provide: API_CONFIG,
useValue: {
baseUrl: '',
centralApiPrefix: '/api/central/v1',
iamApiPrefix: '/api/iam/v1',
crmApiPrefix: '/api/crm/v1',
bpmApiPrefix: '/api/bpm/v1'
}
}
]
};2. Add Toast to app.component.html
<!-- Add to root component template -->
<p-toast></p-toast>
<router-outlet></router-outlet>🚀 Native Federation Integration
This library is designed for @angular-architects/native-federation. Ensure it's marked as singleton in federation.config.js:
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config');
module.exports = withNativeFederation({
shared: {
...shareAll({ singleton: true, strictVersion: false, requiredVersion: false }),
},
skip: [
'@primeuix/themes',
'primeng',
'primeng/**'
]
});Important: All micro-frontends MUST use identical versions of Angular, PrimeNG, and RxJS to avoid runtime errors.
🔧 API Endpoints Configuration
Các interceptors sử dụng các constant URLs. Để customize, tạo environment config:
// environment.ts
export const environment = {
production: false,
apiUrl: 'http://localhost:8000',
iamServiceUrl: 'http://localhost:8001'
};📚 Tham khảo nhanh
Import thường dùng
// Providers
import { provideArdaShared } from 'shared';
// Services
import {
AuthService,
TokenService,
ToastService,
LoadingService,
StorageService,
LoggerService
} from 'shared';
// Guards
import { authGuard, tenantGuard, roleGuard } from 'shared';
// Directives
import {
PermissionDirective,
DebounceDirective,
AutoFocusDirective
} from 'shared';
// Pipes
import { SafeHtmlPipe, TruncatePipe } from 'shared';
// Models
import {
ApiResponse,
PaginationResponse,
SelectOption,
TableColumn
} from 'shared';
// PrimeNG re-exports
import {
ButtonModule,
CardModule,
TableModule,
MenuItem
} from 'shared';🎨 Theme
Shared library cung cấp ArdaPreset - custom PrimeNG theme cho hệ thống Arda.
import { providePrimeNG } from 'primeng/config';
import { ArdaPreset } from 'shared';
providePrimeNG({
theme: {
preset: ArdaPreset
}
})🔐 Security Notes
- Tokens được lưu trong localStorage
- Sensitive data KHÔNG được log trong production
- CORS configuration cần thiết lập đúng trong backend
- Token expiration được check tự động
📝 Best Practices
- Always use ToastService thay vì alert/console.log
- Use LoggerService với proper log levels
- Apply guards cho tất cả protected routes
- Use signals khi possible (AuthService.isAuthenticated)
- Type your API responses với ApiResponse
- Reuse directives thay vì duplicate code
🚀 Roadmap
- [ ] Thêm Notification Service cho real-time notifications
- [ ] Thêm Cache Service cho API caching
- [ ] Thêm Validation Service với custom validators
- [ ] Thêm Form Helpers cho reactive forms
- [ ] Thêm WebSocket Service
- [ ] Thêm i18n Support
📞 Support
Liên hệ team Arda Platform để được hỗ trợ khi sử dụng shared library.
