npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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.

npm version License: MIT

📦 Installation

npm install @arda-labs/core

Peer 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: vinamilk

Error 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

  1. Always use ToastService thay vì alert/console.log
  2. Use LoggerService với proper log levels
  3. Apply guards cho tất cả protected routes
  4. Use signals khi possible (AuthService.isAuthenticated)
  5. Type your API responses với ApiResponse
  6. 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.