Data Model

Data Model terdapat di tiga lokasi pada library keluaran Pagonila.

DataLokasi
Seluruh tabel dan enumerasi basis datayour-blueprint/model
Schemayour-blueprint/engine
Schemayour-blueprint/driver

Models from /model

Seluruh data model basis data dan enumerasi basis data terdapat pada 'your-blueprint/model'. Struktur data disimpan dalam bentuk interface Typescript. Misal pada DBML terdapat tabel seperti berikut:

dan relasi seperti berikut:

maka pada 'your-blueprint/model' akan ada sebuah interface dengan nama ExaminationSession dengan isi seperti berikut:

export interface ExaminationSession {
  id: number;
  user: User;
  user_id?: number;
  examination: Examination;
  examination_id?: number;
  begin_at: Date;
  end_at?: Date;
  certificate_url?: string;
  list_examination_session_q_answer_on_examination_session_id: ExaminationSessionQAnswer[];
}

Relasi foreign key dari user_id dan examination_id otomatis ditambahkan pada kolom instance sebagai data hasil join dengan tabel primary user: User dan examination: Examination.

Relasi primary key yang menunjuk ke tabel ExaminationSession otomatis dideteksi sebagai relasi satu ke banyak (1 to N). Data satu ke banyak ini langsung ditambahkan sebagai larik (list) dari daftar instance tabel yang merujuk ke tabel ExaminationSession, dengan pseudo-format penulisan:

list <Nama Tabel N> <Foreign Key pada Tabel N>: <Nama Tabel N>[]

Seluruh model pada /model telah ditambah dekorator TypeORM sehingga seluruh model tersebut dapat langsung digunakan untuk mengakses basis data.

Schema from /engine

Daftar endpoint API yang didefinisikan pada API Specification didaftarkan sebagai interface Typescript dalam namespace Schema. Misal pada API Specification terdapat data sbb:

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
 
schemas:
  PayloadLogin:
    properties:
      email:
        type: string
        required: true
      password:
        type: string
        required: true

pada namespace Schema akan tersedia struktur data berikut:

 
export declare namespace Schema {
  // berasal dari schemas
  class PayloadLogin {
    'email': string;
    'password': string;
  }
 
  // berasal dari endpoint request
  class PostRequestBodyMasuk {
    'data': PayloadLogin;
  }
  interface PostRequestMasuk {
    body: PostRequestBodyMasuk;
  }
 
  // berasal dari endpoint response
  class PostResponseMasukBody {
    'token': string;
    'user': User;
  }
  type PostResponseMasuk = PostResponseMasukBody;
}

setiap endpoint API akan menghasilkan dua struktur data utama yaitu:

  • Request, dan
  • Response

Request

Struktur data request dihasilkan dengan memecah struktur data berdasarkan lokasi data pada request API tersebut. Terdapat empat lokasi data yang didukung saat ini:

  • body
  • header
  • query
  • path

Setiap lokasi data diatas akan didefinisikan masing-masing sebagai satu buah interface. Misal seperti pada contoh di bawah:

API Specification
title: Sample App
paths:
  /masuk:
    post:
      ...
      parameters:
        data:
          type: PayloadLogin
          required: true
          in: body
      ...
 
...

key data akan masuk ke dalam kelompok lokasi body menghasilkan satu class:

class PostRequestBodyMasuk {
  'data': PayloadLogin;
}

Penamaan class diberikan dengan pseudo-format berikut:

<Metode Endpoint> Request <Lokasi Data> <Path Endpoint>

Jika terdapat parameter lain dengan lokasi yang sama (body) maka akan ditambahkan ke class body, sedangkan jika lokasinya berbeda maka akan menambah interface baru sesuai lokasinya.

Seluruh data pada parameters dengan lokasi yang mungkin berbeda-beda akan dikumpulkan pada sebuah interface request sesuai endpoint API. Misal pada contoh di bawah:

API Specification
title: Sample App
paths:
  /masuk:
    post:
      ...
      parameters:
        data:
          type: PayloadLogin
          required: true
          in: body
      ...

menghasilkan interface request untuk endpoint POST /masuk:

interface PostRequestMasuk {
  body: PostRequestBodyMasuk;
}

Penamaan interface diberikan dengan pseudo-format berikut:

<Metode Endpoint> Request <Path Endpoint>

Response

Data nilai kembalian API return menghasilkan sebuah interface/type response sesuai endpoint API. Misal pada contoh di bawah dimana response diisi dengan bentuk objek children:

API Specification
title: Sample App
paths:
  /masuk:
    post:
      ...
      return:
        type: object
        required: true
        children:
          token:
            type: string
            required: true
          user:
            type: User
            required: true
      ...

data children akan diubah terlebih dahulu menjadi class response dengan endpoint POST /masuk dan menghasilkan:

class PostResponseMasukBody {
  'token': string;
  'user': User;
}

Penamaan class diberikan dengan pseudo-format berikut:

<Metode Endpoint> Response <Path Endpoint> Body

Kemudian untuk response utama, objek response dibungkus menjadi sebuah type menjadi:

type PostResponseMasuk = PostResponseMasukBody;

Penamaan type/interface diberikan dengan pseudo-format berikut:

<Metode Endpoint> Response <Path Endpoint>

Schema

Data schemas yang terdapat pada API Specification menghasilkan masing-masing interface dari setiap skema, misal pada contoh berikut:

API Specification
title: Sample App
paths:
  ...
 
schemas:
  PayloadLogin:
    properties:
      email:
        type: string
        required: true
      password:
        type: string
        required: true

Skema PayloadLogin akan tersedia pada namespace Schema:

class PayloadLogin {
  'email': string;
  'password': string;
}

Schema from /driver

Namespace Schema yang terdapat pada /driver sama persis seperti yang dihasilkan pada /engine.

Fitur TypeORM

Data Model terintegrasi dengan library TypeORM. Seluruh model tabel dan enumerasi telah ditambahkan dekorator TypeORM. Integrasi ini memungkinkan seluruh model basis data yang dihasilkan Pagonila langsung digunakan selayaknya menggunakan model TypeORM.

TypeORM juga memiliki fitur auto-generated migration yang memungkinkan pengguna men-generate script migrasi basis data secara otomatis dan mengaplikasikan script migrasi tersebut ke basis data langsung.

Berikut contoh berkas konfigurasi TypeORM menggunakan data model Pagonila:

data-source.ts
import { DataSource, DataSourceOptions } from "typeorm";
import path from 'path';
import { cwd } from "process";
 
const config: DataSourceOptions = {
  type: "postgres",
  host: '<your db host>',
  port: <your db port number>,
  username: '<your db username>',
  password: '<your db password',
  database: '<your db name>',
  synchronize: false,
  logging: false,
  migrations: [
    __dirname + '/migration/**.ts'
  ],
  entities: [
    path.resolve(cwd(), 'node_modules/your-blueprint/model.js')
  ]
};
 
export const AppDataSource = new DataSource(config);

Lalu untuk menjalankan auto-generated migration dan melakukan migrasi basis data, dapat dilakukan dengan menambahkan script berikut pada package.json

package.json
...
 
  "scripts": {
    ...
    "typeorm": "typeorm-ts-node-commonjs",
    "generate-migration": "npm run typeorm migration:generate -- $1 -d ./data-source.ts",
    "migrate": "npm run typeorm migration:run -- -d ./data-source.ts"
  }
...

Untuk men-generate berkasi migrasi basis data dapat dilakukan dengan cara berikut:

# "Init" dapat diganti dengan nama lain
npm run generate-migration migration/Init

dan untuk melakukan migrasi ke basis data dengan cara berikut:

npm run migrate
Outline