Loading ...

icon
...Muhammet Ali Çomak
23 Temmuz 2024

TypeScript ile Automapper kütüphanesi

Öncelikle bu kütüphane ne işe yarar ondan bahsedelim.  Nesneleri maplemek için kullandığımız bir kütüphanedir. Örnek verecek olursak client tarafına gereksiz veya gösterilmemesi gereken bazı veri tabanı bilgileri vardır. Mesela kullanıcı şifresi.  Evet şifreyi hashliyoruz ancak yine de gönderilmesi mantıksızdır ve güvenlik açığı oluşabilir. Bu gibi durumların önüne geçmek için bu kütüphaneyi kullanıyoruz. 

Eee tamam da biz bunu tek tek de yapabiliriz gerek varmı ki?

- Cevabımız evet var maaliyet ve zaman kazandırıyor.

Çok basit projelerde kullanmak mantıklı olmayabilir ancak içeriği çok fazla olan nesneyi, dto nesnesine tek tek yazarak aktarmak doğal olarak yorucu olur.  

Bu kütüphane .NET tarafında da var ve Türkçe kaynak çok fazla olduğu için burada anlatılmasını gereksiz buluyorum. Ancak Typescript tarafında nasıl kullanıldığına dair Türkçe kaynak göremediğim için ben yapma kararı aldım. :)

Öncelikle 2 adet npm paketini projemize dahil etmeliyiz.

npm i @automapper/core
npm i @automapper/classes

Daha sonra maplenecek nesnelerimizi automappera bildirmemiz gerekiyor.

User entity nesnesi:

import { AutoMap } from '@automapper/classes';
import BaseEntity from './BaseEntity';

export default class User extends BaseEntity {

    @AutoMap()
    UserName!: string;
    @AutoMap()
    Email!: string;
    @AutoMap()
    Password!: string;
    @AutoMap()
    PasswordUpdateDate!: string;

    @AutoMap()
    ProfileImage!: string | null | undefined;

    constructor(init?: Partial<User>) {
        super();
        Object.assign(this, init);
    }

}

Bu projemizde BaseEntity nesnemizde var aynı işlemi onada uygulayalım.

import { AutoMap } from '@automapper/classes';
export default class BaseEntity {
    
    @AutoMap()
    id?: string;
    @AutoMap()
    createDate?: string;
    @AutoMap()
    updateDate?: string;

    constructor(init?: Partial<BaseEntity>) {
        Object.assign(this, init);
    }
}

Bu şekilde @AutoMap() ile entity nesnemizin içeriğini bildiriyoruz.

Aynı işlemi dto içinde yapmalıyız.

UserDto nesnesi:

import { AutoMap } from '@automapper/classes';
export default class UserDto {


    @AutoMap()
    UserName!: string;

    @AutoMap()
    Email!: string;

    @AutoMap()
    ProfileImage!: string;

    @AutoMap()
    updateDate!: string;
    constructor(init?: Partial<UserDto>) {
        Object.assign(this, init);
    }
}

Ancak bir sorunumuz var TypeScript yapılandırmamız eğer bazı ayarlarımız eksikse burada hata verecektir. Bu yüzden tsconfig.ts dosyamız bu şekilde olmalı.

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "./dist",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": [
    "app.ts"
  ],
  "exclude": [
    "node_modules"
  ],
}

Artık işimiz bitti MapProfile adında kendi fonksiyonumuzu oluşturup hangi nesnelerin nasıl mapleneceği hakkında automappera bilgi verelim.

MapProfile.ts dosyası:

import { createMap, createMapper, forMember, mapFrom } from '@automapper/core';
import UserDto from '../../DTOs/UserDto';
import User from '../../entities/User';

export const mapper = createMapper({
    strategyInitializer: classes(),
});

createMap(mapper, User, UserDto);

İşte burada son işlemimizi yapmış oluyoruz. Artık User nesnesi UserDto nesnesine maplenebilecek. createMap() fonksiyonu ile istediğimiz maplenecek nesneleri yazabiliriz. Peki nasıl kullanacağız.

    async GetProfile(UserId: string): Promise<UserDto> {
        const UserInformation = await this._UserRepository.GetByIdAsync(UserId);
        let mapping = await mapper.mapAsync(UserInformation, User, UserDto);
        return (mapping);
    }

Burada da  Service katmanımızda nasıl nesneyi mapleyip kullancağımızın örneği vardır. 

Çok fazla fonksiyon içeriğide mevcut maplenirken istediğimiz nesnenin alanına başka değerler de atayabiliyoruz örnek olarak :

createMap(mapper, RegisterDto, User,
    forMember((destination) => destination.createDate, mapFrom(() => new Date().toISOString()))
);

Burada RegisterDto User nesnesine maplenirken createDate alanımıza günün tarihini atıyorum. Ve ben bu mapleme işlemini her kullandığımda artık tek tek elimle bu tarih atamasını yazmam gerekmeyecek.

Daha fazlası için ilgili döküman: https://automapperts.netlify.app/.  

Son olarak okuduğun için teşekkür ederim. :)

Daha fazlası için