feat(core-api): implement abstract data transformer architecture

- **Core API**: Introduced `IDataTransformer` interface and `BaseDataTransformer` abstract class.
- **Data Services**: Updated `BaseRemoteDataServices` and `DataServicesConfig` to support optional transformer injection. CRUD methods now auto-transform data mapping (DTO <-> Entity) when a transformer is provided.
- **Generics**: Updated `CommonRemoteDataServices` to forward the `TDTO` generic for strict type safety. Fixed `ApiResponse<T>` casting and excess property type checks.
- **Showcase/Samples**: Created `BookingTransformer` (snake_case to camelCase mapping) and injected it into `booking.data-services.ts`.
- **Advanced Showcase**: Added `AdvancedBookingTransformer` and `AdvancedBookingService` to demonstrate extending base transformers with custom methods (e.g., `getAvailabilityChart`).
- **Documentation**: Added comprehensive developer guide at `apps/docs-dev/src/packages/core-api/transformers.md`.
- **Testing**: Added 16 new unit tests for transformer integrations (identity and mock scenarios).

Note: The implementation is 100% backward compatible. All 49/49 tests pass and the TypeScript typecheck is entirely clean.
This commit is contained in:
Firman Ramdhani
2026-07-01 11:13:09 +07:00
parent 7130eb3fe3
commit 1c2090f4fb
11 changed files with 1494 additions and 19 deletions
@@ -12,11 +12,12 @@ import { BaseRemoteDataServices } from './base-remote.data-services';
* CRUD + lifecycle, extend BaseRemoteDataServices instead and add
* custom methods using `this.execute()` or `this.customRequest()`.
*
* @typeParam E - The domain entity type
* @typeParam E - The domain entity type
* @typeParam TDTO - The API DTO shape (defaults to E for backward compatibility)
*
* @example
* ```ts
* // Direct instantiation for standard modules
* // Direct instantiation for standard modules (no transformer)
* const bookingServices = new CommonRemoteDataServices<BookingEntity>(
* apiClient,
* { apiUrl: '/bookings', moduleKey: 'BOOKING' },
@@ -27,6 +28,19 @@ import { BaseRemoteDataServices } from './base-remote.data-services';
*
* @example
* ```ts
* // With transformer for DTO ↔ Entity mapping
* const bookingServices = new CommonRemoteDataServices<BookingEntity, BookingDTO>(
* apiClient,
* {
* apiUrl: '/bookings',
* moduleKey: 'BOOKING',
* transformer: new BookingTransformer(),
* },
* );
* ```
*
* @example
* ```ts
* // For modules needing custom operations, extend the base:
* class InvoiceDataServices extends BaseRemoteDataServices<InvoiceEntity> {
* async calculateTax(invoiceId: string) {
@@ -40,4 +54,6 @@ import { BaseRemoteDataServices } from './base-remote.data-services';
*/
export class CommonRemoteDataServices<
E extends BaseEntity = BaseEntity,
> extends BaseRemoteDataServices<E> {}
TDTO = E,
> extends BaseRemoteDataServices<E, TDTO> {}