@flusys/ng-core
v4.1.1
Published
Core utilities and services for FLUSYS Angular packages
Readme
@flusys/ng-core
Foundation library for the FLUSYS Angular platform — configuration injection, base HTTP services, API loaders, and HTTP interceptors.
Table of Contents
- Overview
- Features
- Compatibility
- Installation
- Quick Start
- Configuration Reference
- Base Services
- HTTP Interceptors
- Helper Functions
- Exported Tokens
- Troubleshooting
- License
Overview
@flusys/ng-core is the zero-dependency foundation of the FLUSYS Angular package hierarchy. Every other FLUSYS Angular package depends on it. It provides:
- The
APP_CONFIGinjection token — single source of truth for all application configuration BaseApiService— typed POST-only RPC HTTP clientApiLoaderService— manages global loading state across concurrent requests- HTTP interceptors — base URL injection and error normalization
- Utility helper functions for feature detection
This package has no FLUSYS dependencies — it only depends on Angular core.
Features
- ✅ Typed
IAppConfigwith full IntelliSense - ✅ POST-only RPC HTTP client (
BaseApiService) - ✅ Global loading state management (
ApiLoaderService) - ✅
APP_CONFIGinjection token for DI-based configuration - ✅ Feature detection helpers (
isAuthEnabled(),isIamEnabled(),isSignUpEnabled(), etc.) - ✅ HTTP interceptors for base URL and error handling
- ✅ Zoneless-compatible (no Zone.js dependency)
- ✅ Signal-friendly architecture
Compatibility
| Package | Version | |---------|---------| | Angular | 21+ | | TypeScript | 5.x | | RxJS | 7.x |
Installation
npm install @flusys/ng-coreQuick Start
1. Define App Config
// environments/environment.ts
import { IAppConfig } from '@flusys/ng-core';
export const environment: IAppConfig = {
appName: 'My App',
apiBaseUrl: 'http://localhost:2002',
production: false,
services: {
auth: {
enabled: true,
features: {
signUp: true,
emailVerification: true,
},
},
iam: { enabled: true },
storage: { enabled: true },
email: { enabled: false },
formBuilder: { enabled: false },
eventManager: { enabled: false },
notification: { enabled: false },
localization: { enabled: false },
},
multiTenant: false,
permissionMode: 'FULL',
};2. Provide Config in app.config.ts
import { ApplicationConfig } from '@angular/core';
import { APP_CONFIG } from '@flusys/ng-core';
import { environment } from './environments/environment';
export const appConfig: ApplicationConfig = {
providers: [
{ provide: APP_CONFIG, useValue: environment },
// ... other providers
],
};3. Inject Config Anywhere
import { inject } from '@angular/core';
import { APP_CONFIG, IAppConfig } from '@flusys/ng-core';
@Injectable({ providedIn: 'root' })
export class MyService {
private config = inject<IAppConfig>(APP_CONFIG);
getApiUrl(): string {
return this.config.apiBaseUrl;
}
}Configuration Reference
IAppConfig
Complete configuration interface for the FLUSYS platform:
interface IAppConfig {
/** Application display name */
appName: string;
/** Backend API base URL */
apiBaseUrl: string;
/** Production mode flag */
production: boolean;
/** Multi-tenant mode — isolates data per company */
multiTenant?: boolean;
/** IAM permission evaluation mode */
permissionMode?: 'RBAC' | 'DIRECT' | 'FULL';
services: {
auth?: {
enabled: boolean;
features?: {
/** Allow self-registration */
signUp?: boolean;
/** Email verification on register */
emailVerification?: boolean;
/** Require company selection after login */
companySelection?: boolean;
};
};
iam?: { enabled: boolean };
storage?: { enabled: boolean };
email?: { enabled: boolean };
formBuilder?: { enabled: boolean };
eventManager?: { enabled: boolean };
notification?: { enabled: boolean };
localization?: { enabled: boolean };
};
}APP_CONFIG Token
import { APP_CONFIG } from '@flusys/ng-core';
// In component/service
const config = inject<IAppConfig>(APP_CONFIG);Base Services
BaseApiService
Typed HTTP client configured for POST-only RPC endpoints. All FLUSYS API services extend this class.
import { BaseApiService, ISingleResponse, IListResponse } from '@flusys/ng-core';
@Injectable({ providedIn: 'root' })
export class ProductApiService extends BaseApiService {
protected resource = 'product';
getAll(params: IListParams): Observable<IListResponse<Product>> {
return this.post(`${this.resource}/get-all`, params);
}
getById(id: string): Observable<ISingleResponse<Product>> {
return this.post(`${this.resource}/get/${id}`, {});
}
insert(data: CreateProductDto): Observable<ISingleResponse<Product>> {
return this.post(`${this.resource}/insert`, data);
}
update(data: UpdateProductDto): Observable<ISingleResponse<Product>> {
return this.post(`${this.resource}/update`, data);
}
delete(id: string): Observable<IMessageResponse> {
return this.post(`${this.resource}/delete`, { id });
}
}Key Methods:
| Method | Signature | Description |
|--------|-----------|-------------|
| post<T> | (path, body, options?) | POST request with automatic base URL |
| get<T> | (path, options?) | GET request (rarely used in FLUSYS) |
| setLoader | (show: boolean) | Manually toggle loading indicator |
BaseApiService automatically:
- Prepends
apiBaseUrlfromAPP_CONFIG - Sets
Content-Type: application/json - Triggers
ApiLoaderServicefor loading state - Normalizes errors through
GlobalErrorHandler
ApiLoaderService
Tracks concurrent HTTP requests to show/hide global loading indicators.
import { ApiLoaderService } from '@flusys/ng-core';
@Component({ ... })
export class AppComponent {
private loader = inject(ApiLoaderService);
// Reactive loading state (signal)
isLoading = this.loader.isLoading;
}<!-- Use in template -->
@if (isLoading()) {
<p-progressBar mode="indeterminate" />
}ApiLoaderService API:
| Member | Type | Description |
|--------|------|-------------|
| isLoading | Signal<boolean> | True when any HTTP request is pending |
| increment() | void | Manually increment request counter |
| decrement() | void | Manually decrement request counter |
HTTP Interceptors
@flusys/ng-core provides base HTTP interceptors registered via provideHttpClient:
Base URL Interceptor
Automatically prepends APP_CONFIG.apiBaseUrl to all relative HTTP requests.
// Absolute URLs are passed through unchanged
// Relative URLs like '/auth/login' become 'http://localhost:2002/auth/login'Error Normalizer Interceptor
Normalizes all HTTP error responses into a consistent IErrorResponse shape before they reach your services.
Registering Interceptors
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { baseUrlInterceptor, errorNormalizerInterceptor } from '@flusys/ng-core';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([
baseUrlInterceptor,
errorNormalizerInterceptor,
])
),
],
};Helper Functions
Feature detection helpers that read from APP_CONFIG:
import {
isAuthEnabled,
isIamEnabled,
isStorageEnabled,
isSignUpEnabled,
isEmailVerificationEnabled,
isCompanySelectionEnabled,
isLocalizationEnabled,
isNotificationEnabled,
} from '@flusys/ng-core';
// Usage in a service or guard
const authOn = isAuthEnabled(config); // boolean
const iamOn = isIamEnabled(config); // boolean
const storageOn = isStorageEnabled(config); // boolean
const signUpOn = isSignUpEnabled(config); // booleanExported Tokens
| Token | Type | Description |
|-------|------|-------------|
| APP_CONFIG | InjectionToken<IAppConfig> | Global app configuration |
| TRANSLATE_ADAPTER | InjectionToken<ITranslateAdapter> | Localization adapter interface |
Troubleshooting
NullInjectorError: No provider for APP_CONFIG
You forgot to provide APP_CONFIG in app.config.ts:
providers: [
{ provide: APP_CONFIG, useValue: environment },
]Cannot read properties of undefined (reading 'apiBaseUrl')
APP_CONFIG was provided but the environment object is missing the required field. Check that your environment file implements the full IAppConfig interface.
HTTP 404 on API requests
Check that apiBaseUrl does not have a trailing slash:
// ❌ Wrong
apiBaseUrl: 'http://localhost:2002/'
// ✅ Correct
apiBaseUrl: 'http://localhost:2002'License
MIT © FLUSYS
