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

@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-lib

Peer 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)

  1. Create a config.json file in your assets folder with Keycloak settings.
  2. Load it at app startup and provide it to KEYCLOAK_CONFIG using an APP_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 KeycloakService to 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 BaseTaskDashboardComponent from core-lib for listing and managing tasks.
  • Details Component: Extends BaseFormComponent or BaseTaskDetailsComponent for task details and editing.
  • Models: Define task models extending BaseTaskModel and 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.