Backend Engine

Library Engine Pagonila digunakan sebagai server Backend. Engine ini merupakan sebuah instance ExpressJS yang dibungkus dengan beberapa fitur otomatis seperti:

  • Validasi request
  • Transformasi request
  • Error handling
  • Response handling

Engine dapat diakses melalui namespace Backend pada path /your-blueprint/engine. Pada namespace Backend terdapat class Engine.

Backend.Engine

class Backend.Engine
namespace Backend {
  class Engine {
    express?: Express;
    init(param: SystemParam): Promise<Engine>;
    implement(module: ModuleStub): void;
  }
}
 
Atribut/MetodePenjelasan
expressInstance ExpressJS yang dijalankan sebagai server. Instane ini dapat digunakan untuk mengimplementasi fitur yang tidak diakomodasi Pagonila
initMetode untuk menginisialisasi/menjalankan backend server
implementMetode untuk mengimplementasi stub fungsi yang didefinisikan pada spesifikasi API

Backend.SystemParam

Kelas Backend.Engine tidak memiliki konstruktor khusus, namun harus diinisialisasi dengan metode init dengan parameter Backend.SystemParam.

interface Backend.SystemParam
namespace Backend {
  class Engine ...
 
  interface SystemParam {
    port?: number;
    beforeStart?(): Promise<void>;
  }
}
ParameterNilai defaultPenjelasan
port3000Port server dijalankan
beforeStartundefinedFungsi asinkronus yang dijalankan sebelum ExpressJS mulai menjalankan HTTP Server pada port yang telah ditentukan. Dapat digunakan untuk menginisialisasi basis data seperti TypeORM.

Engine.implement()

Metode implement() yang ada pada kelas Engine hanya akan dijalankan setelah metode init dijalankan terlebih dahulu. Metode implement() memiliki satu parameter berjenis ModuleStub, dimana ModuleSub adalah sebuah interface daftar spesifikasi API dengan format seperti berikut:

ModuleStub
interface ModuleSub {
  path: string;
  method: string;
  fn: (param: RequestType) => Promise<ResposeType>;
}

path dan method merupakan endpoint path yang telah didefinisikan sebelumnya pada spesifikasi API. Misal pada spesifikasi API berikut:

API Specification
title: Sample App
paths:
  /masuk:
    post:
      summary: |-
        Masuk ke akun yang
        sudah terdaftar
      parameters:
        data:
          type: PayloadLogin
          required: true
          in: body
      return:
        type: object
        required: true
        children:
          token:
            type: string
            required: true
          user:
            type: User
            required: true

akan menghasilkan sebuah interface ModuleStub kira-kira seperti ini:

Contoh ModuleStub
type IPostMasuk = (param: Schema.PostRequestMasuk) => Promise<Schema.PostResponseMasuk>
 
interface T_MasukPost {
  path: '/masuk';
  method: 'post';
  fn: IPostMasuk;
}

Fungsi lambda fn selanjutnya harus diimplementasi sebagai logika dari proses API tersebut. Melalui mekanisme implementasi API seperti ini, pengguna tidak perlu lagi melakukan validasi request dari pengguna karena otomatis telah divalidasi dan ditransformasi ke format sesuai spesifikasi API oleh backend Pagonila. Setiap kali fungsi fn dieksekusi berarti data telah sesuai dengan format yang telah dituliskan pada spesifikasi API.

Dalam memberikan respon nilai kembalian dari sebuah API, Pagonila memiliki mekanisme khusus berdasarkan dua kasus:

  • Berhasil
  • Gagal

Respon Berhasil

Respons berhasil akan dikembalikan dengan kode http 200. Saat ini Pagonila hanya mendukung kode 200 sebagai hasil respon berhasil. Selain itu, pengguna juga harus disiplin dalam mengembalikan respon sesuai dengan struktur data yang telah didefinisikan pada spesifikasi API.

Misal menggunakan contoh ModuleStub pada contoh di atas, implementasi akan kurang-lebih seperti ini:

Implementasi Login
engine.implement({
  path: '/masuk',
  method: 'post',
  async fn(param) {
    
    // proses lain...
 
    const sample_user: User = await ORM.getUser();
    const nilai_kembalian: Schema.PostResponseMasuk = {
      token: 'sample jwt token',
      user: sample_user
    };
 
    return nilai_kembalian;
  }
});

dengan return statement selain struktur data Schema.PostResponseMasuk, Typescript akan mengeluarkan pesan kompilasi error.

Respon Gagal

Dalam mengembalikan respon gagal, Pagonila menggunakan mekanisme yang sederhana yaitu menggunakan throws Error(error: string). Ketika melakukan throws Error, terdapat dua macam cara yang dapat dilakukan:

  • dengan kode HTTP, atau
  • tanpa kode HTTP

Pengembalian respon error tanpa kode HTTP dapat dilakukan dengan langsung melepaskan Error dengan parameter string.

Contoh respon error tanpa kode HTTP
engine.implement({
  path: '/masuk',
  method: 'post',
  async fn(param) {
    // proses lain...
 
    throw new Error(`Contoh pesan error`);
 
    // proses lain...
  }
});

Pesan error tanpa kode HTTP otomatis mengembalikan kode HTTP error 400. Pengembalian respon error dengan kode HTTP dilakukan dengan menuliskan parameter string yang didahului kode HTTP lalu dipisah dengan kolon (titik dua), dilanjutkan dengan pesan error-nya.

Contoh respon error dengan kode HTTP
engine.implement({
  path: '/masuk',
  method: 'post',
  async fn(param) {
    // proses lain...
 
    throw new Error(`401: Anda tidak diijinkan mengakses akun ini`);
 
    // proses lain...
  }
});

Contoh diatas menghasilkan pesan error Anda tidak diijinkan mengakses akun ini dengan kode respon HTTP 401.

Outline