simple-abstract-ui-data-adapter

This is a simple abstract ui data adapter that will help you separate api data from ui data.


Keywords
web, front-end, typescript
License
MIT
Install
npm install simple-abstract-ui-data-adapter@1.0.0

Documentation

This is a simple abstract ui data adapter that will help you separate api data from ui data.

Installation

npm install simple-abstract-ui-data-adapter
# or
yarn add simple-abstract-ui-data-adapter

Define your ui interface:

interface CarUiInterface {
    id: string;
    brand: string;
    model: string;
    launchDate: Date;
}

Your api response data for getting a car:

interface GetCarApiResponseData {
    id: number;
    brand: string;
    model: string:
    launch_date: string;
}

Create an ui adapter class that implements this interface and then extend AbstractUiAdapter. It accepts as generic the interface for api response data.

import { AbstractUiAdapter } from 'simple-abstract-ui-data-adapter';

class CarUiAdapter
extends AbstractUiAdapter<GetCarApiResponseData>
implements CarUiInterface
{
    id: string;
    
    brand: string;
    
    model: string;
    
    launchDate: Date;
    
    protected applyAttributes(apiData: GetCarApiResponseData): void {
        this.id = apiData.id.toString();
        this.brand = apiData.charAt(0).toUpperCase() + apiData.slice(1); // pretend you need brand string capitalized
        this.model = apiData.model;
        this.launchDate = new Date(apiData.launch_date);
    }
    
    protected applyRuntimeValidations() {
        if (Number.isNaN(this.launchDate.getTime())) {
            throw new Error('Invalid date string received from api!');
        }
    }
}

How to use:

const carModel = await CarUiAdapter.create<GetCarApiResponseData, CarUiInterface>(apiData);

Reduce boilerplate using a helper like this:

export class CarUiHelper {
    public static async getUiModel(apiData: GetCarApiResponseData): CarUiInterface {
        return CarUiAdapter.create<GetCarApiResponseData, CarUiInterface>(apiData);
    }
}

Simple usage:

const carModel = CarUiHelper.getUiModel(apiData);

Now let's pretend your api structure changed, or you use a new API with a completely different structure. The only place in your app where you will need to make changes is implementation of method applyAttributes(apiData: GetCarApiResponseData): void.

New API interface:

interface GetCarApiResponseData {
    id: number;
    brandWithModel: string;
    launch_date: number;
}

Required updates:

protected applyAttributes(apiData: GetCarApiResponseData): void {
    this.id = apiData.id.toString();
    const brandAndModel = apiData.brandWithModel.split(" ");
    this.brand = brandAndModel[0].charAt(0).toUpperCase() + apiData.slice(1);
    this.model = brandAndModel[1];
    this.launchDate = new Date(apiData.launch_date);
}