@c-a-f/core
v1.0.4
Published
Clean Architecture Frontend (CAF) — domain-agnostic primitives: UseCase, Ploc, Pulse, ApiRequest, RouteManager. Build frontend apps with Clean Architecture.
Maintainers
Readme
@c-a-f/core
Domain-agnostic primitives for clean architecture frontends: UseCase, Ploc, Pulse, ApiRequest, RouteManager.
Documentation: @c-a-f/core docs
Installation
npm install @c-a-f/coreUsage
UseCase
Define application use cases that return Promise<RequestResult<T>>:
import { UseCase, RequestResult } from '@c-a-f/core';
interface LoginUserArgs {
username: string;
password: string;
}
class LoginUser implements UseCase<[LoginUserArgs], { token: string }> {
async execute(args: LoginUserArgs): Promise<RequestResult<{ token: string }>> {
// Your login logic here
const result = await loginService.login(args);
return {
loading: pulse(false),
data: pulse(result),
error: pulse(null! as Error),
};
}
}Ploc (Presentation Logic Component)
Create stateful presentation logic containers:
import { Ploc } from '@c-a-f/core';
interface CounterState {
count: number;
isLoading: boolean;
}
class CounterPloc extends Ploc<CounterState> {
constructor() {
super({ count: 0, isLoading: false });
}
increment() {
this.changeState({ ...this.state, count: this.state.count + 1 });
}
subscribeToState(listener: (state: CounterState) => void) {
this.subscribe(listener);
}
}
// Usage
const counter = new CounterPloc();
counter.subscribe((state) => console.log('Count:', state.count));
counter.increment(); // Logs: Count: 1Pulse (Single Reactive Value)
For single reactive values:
import { pulse } from '@c-a-f/core';
const count = pulse(0);
count.subscribe((value) => console.log('Value:', value));
count.value = 5; // Logs: Value: 5ApiRequest
Wrap async requests with reactive loading/data/error state:
import { ApiRequest, IRequestHandler } from '@c-a-f/core';
// Works with Promise (backward compatible)
const fetchUser = new ApiRequest(fetch('/api/user').then(r => r.json()));
// Or with IRequestHandler for flexibility (real API, mocks, cached)
class ApiRequestHandler<T> implements IRequestHandler<T> {
constructor(private apiCall: () => Promise<T>) {}
async execute(): Promise<T> {
return await this.apiCall();
}
}
const userRequest = new ApiRequest(
new ApiRequestHandler(() => fetch('/api/user').then(r => r.json()))
);
userRequest.loading.subscribe((loading) => {
if (loading) console.log('Loading...');
});
userRequest.data.subscribe((data) => {
console.log('User:', data);
});
await userRequest.mutate();RouteManager
Coordinate routing (requires a RouteRepository implementation from your framework):
import { RouteManager, RouteRepository } from '@c-a-f/core';
// Your framework adapter implements RouteRepository
const routeRepository: RouteRepository = {
currentRoute: '/',
change: (route) => router.push(route),
};
const routeManager = new RouteManager(routeRepository, {
loginPath: '/login',
isLoggedIn: () => !!localStorage.getItem('token'),
});
routeManager.changeRoute('/dashboard');
routeManager.checkForLoginRoute(); // Redirects to /login if not authenticatedExports
UseCase— Interface for application use casesPloc— Abstract class for presentation logic containersPulse— Class for single reactive valuespulse— Factory function for creating Pulse instancesApiRequest— Class for wrapping async requestsRouteManager— Class for coordinating routingRouteRepository— Interface for routing system abstractionRouteManagerAuthOptions— Interface for auth configurationRequestResult— Type for use case resultsIRequest— Type for async requestsIApiClient— Interface for API client implementationsApiRequestConfig— Interface for API request configurationApiResponse— Interface for standard API response wrapperApiError— Interface for standard API error formatHttpMethod— Type for HTTP method typesextractApiData— Helper function to extract data from wrapped responsesnormalizeApiError— Helper function to normalize errorsIRequestHandler— Interface for request handler implementations (allows swapping real API, mocks, cached)PromiseRequestHandler— Adapter class to convert Promise to IRequestHandlertoRequestHandler— Helper function to normalize requests to IRequestHandler
Documentation
- @c-a-f/core documentation — Package docs, usage, and API
- Full API Documentation — Complete API reference (repo)
- Main Repository README — Architecture overview and getting started
- Publishing Guide — How to publish and consume packages
- Versioning Strategy — Versioning approach
License
MIT
