@codex-ts/core-lib
v1.1.6
Published
Reusable Angular library for enterprise applications, providing dynamic forms, CRUD services, and Keycloak-based authentication.
Readme
CoreLib
Reusable Angular library for enterprise applications, providing dynamic forms, CRUD services, and Keycloak-based authentication.
Overview
CoreLib offers:
- Abstract components for forms, lists, and dashboards
- Generic CRUD services
- Strongly-typed models and enums
- Keycloak authentication and route protection
- Signal-based error handling and state management
- Built-in error pages and components
- Utilities for state management and notifications
Installation
npm install @codex-ts/core-libPeer dependencies (install in your app if not present):
@angular/core,@angular/common,@ngx-formly/core,primeng,rxjs,keycloak-js
Setup
Configuring Keycloak with Environment Properties
You can configure Keycloak using environment-specific properties to avoid hardcoding sensitive values.
Option 1: Using Angular's environment.ts
Set your Keycloak config in src/environments/environment.ts:
// environment.ts
export const environment = {
production: false,
keycloak: {
authServerUrl: 'https://<keycloak-server>/auth',
realm: '<realm>',
clientId: '<client-id>',
options: {
loginRedirect: '/dashboard',
bearerToken: true,
excludedUrls: ['/assets', '/public'],
roles: ['user', 'admin'],
tokenValidityThreshold: 60
}
}
};Then provide it in your app module:
import { environment } from '../environments/environment';
import { KEYCLOAK_CONFIG } from '@codex-ts/core-lib';
providers: [
{
provide: KEYCLOAK_CONFIG,
useValue: environment.keycloak
}
]Option 2: Using Runtime Environment (e.g., assets/config.json)
- Create a
config.jsonfile in yourassetsfolder with Keycloak settings. - Load it at app startup and provide it to
KEYCLOAK_CONFIGusing anAPP_INITIALIZER.
Example:
// assets/config.json
{
"authServerUrl": "https://<keycloak-server>/auth",
"realm": "<realm>",
"clientId": "<client-id>",
"options": {
"loginRedirect": "/dashboard",
"bearerToken": true
}
}// app.module.ts
import { HttpClient } from '@angular/common/http';
import { APP_INITIALIZER } from '@angular/core';
import { KEYCLOAK_CONFIG } from '@codex-ts/core-lib';
export function loadConfig(http: HttpClient) {
return () => http.get('/assets/config.json')
.toPromise()
.then(config => {
(window as any).keycloakConfig = config;
});
}
providers: [
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [HttpClient],
multi: true
},
{
provide: KEYCLOAK_CONFIG,
useFactory: () => (window as any).keycloakConfig
}
]This allows you to change Keycloak settings without rebuilding the app.
1. Import the Library Module
import { CoreLibModule } from '@codex-ts/core-lib';
@NgModule({
imports: [CoreLibModule, ...]
})
export class AppModule {}2. Configure Keycloak
Provide Keycloak configuration in your app module:
import { KEYCLOAK_CONFIG } from '@codex-ts/core-lib';
providers: [
{
provide: KEYCLOAK_CONFIG,
useValue: {
authServerUrl: 'https://<keycloak-server>/auth',
realm: '<realm>',
clientId: '<client-id>',
options: {
loginRedirect: '/dashboard',
bearerToken: true,
excludedUrls: ['/assets', '/public'],
roles: ['user', 'admin'],
tokenValidityThreshold: 60
}
}
}
]3. Register Interceptor and Guard
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { KeycloakAuthInterceptor, KeycloakAuthGuard } from '@codex-ts/core-lib';
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: KeycloakAuthInterceptor, multi: true },
KeycloakAuthGuard
]4. Protect Routes
{
path: 'secure',
component: SecureComponent,
canActivate: [KeycloakAuthGuard],
data: { roles: ['admin'] }
}Usage
- Use provided base components and services for forms, lists, and CRUD operations.
- Inject
KeycloakServiceto access authentication state, user info, and roles.
constructor(private keycloak: KeycloakService) {}
ngOnInit() {
if (this.keycloak.isAuthenticated$()) {
// User is authenticated
}
}KeycloakService API
initialize(): Initializes Keycloak.login(),logout(): Triggers login/logout.getToken(): Gets current access token.getRoles(),hasRole(role): Role management.userProfile$: Observable for user profile.
Example:
if (this.keycloak.hasRole('admin')) {
// Show admin features
}Troubleshooting
- Ensure Keycloak server is reachable.
- Check DI configuration for KEYCLOAK_CONFIG.
- Use browser console for error logs from KeycloakService.
Contributing
- Fork, branch, and submit PRs.
- Write unit tests for new features.
License
MIT
Error Handling
CoreLib provides a comprehensive, signal-based error handling system:
Features
- Centralized error state management using Angular signals
- Built-in error pages for common scenarios (404, 401, etc.)
- Dynamic error messages and status codes
- Automatic cleanup on navigation
- Toast notifications for non-critical errors
Usage Example
// 1. Error Service in your components/services
constructor(private readonly errorService: BaseErrorService) {}
try {
// Your code
} catch (error) {
this.errorService.handleError(error);
}
// 2. React to errors in components
export class YourComponent {
private readonly errorService = inject(ERROR_SERVICE);
readonly error = this.errorService.error;
get errorMessage(): string {
return this.error()?.message ?? "Default message";
}
}Error Types
- HTTP errors (401, 403, 404, 500, etc.)
- Connection errors
- Client-side errors
- Application-specific errors
Built-in Error Pages
- NotFoundComponent (404)
- UnauthorizedComponent (401/403)
- All error pages use signals for dynamic content
Benefits
- Single source of truth for error handling
- Reactive updates with signals
- Consistent error handling across the application
- Improved debugging with error context
- Clean separation of error handling logic
Task Management Implementation Example
This section demonstrates how to use core-lib to implement a typical task management module in your Angular application.
Structure
- Dashboard Component: Extends
BaseTaskDashboardComponentfrom core-lib for listing and managing tasks. - Details Component: Extends
BaseFormComponentorBaseTaskDetailsComponentfor task details and editing. - Models: Define task models extending
BaseTaskModeland related interfaces. - Service: Implements CRUD operations by extending
BaseCrudService.
Example
1. Task Model
import { BaseTaskModel } from '@codex-ts/core-lib';
export interface CustomerServiceTask extends BaseTaskModel {
// Add custom fields here
status: string;
assignedTo: string;
}2. Task Service
import { Injectable } from '@angular/core';
import { BaseCrudService } from '@codex-ts/core-lib';
import { CustomerServiceTask } from './models/customer-service-task.model';
@Injectable({ providedIn: 'root' })
export class CustomerServiceTaskService extends BaseCrudService<CustomerServiceTask> {
constructor(/* inject dependencies */) {
super(/* pass dependencies and resource path */);
}
}3. Dashboard Component
import { Component } from '@angular/core';
import { BaseTaskDashboardComponent } from '@codex-ts/core-lib';
import { CustomerServiceTaskService } from './customer-service-task.service';
import { CustomerServiceTask } from './models/customer-service-task.model';
@Component({
selector: 'app-customer-service-task-dashboard',
templateUrl: './customer-service-task-dashboard.component.html'
})
export class CustomerServiceTaskDashboardComponent
extends BaseTaskDashboardComponent<CustomerServiceTask> {
constructor(protected customerServiceTaskService: CustomerServiceTaskService) {
super(customerServiceTaskService);
}
}4. Details Component
import { Component } from '@angular/core';
import { BaseFormComponent } from '@codex-ts/core-lib';
import { CustomerServiceTaskService } from './customer-service-task.service';
import { CustomerServiceTask } from './models/customer-service-task.model';
@Component({
selector: 'app-customer-task-details',
templateUrl: './customer-task-details.component.html'
})
export class CustomerTaskDetailsComponent
extends BaseFormComponent<CustomerServiceTask> {
constructor(protected customerServiceTaskService: CustomerServiceTaskService) {
super(customerServiceTaskService);
}
}5. Routing and Guards
Protect routes using KeycloakAuthGuard and specify roles as needed:
{
path: 'tasks',
component: CustomerServiceTaskDashboardComponent,
canActivate: [KeycloakAuthGuard],
data: { roles: ['admin', 'user'] }
}Notes
- Use the provided base components and services for rapid development and consistency.
- Extend models and services as needed for your domain.
