Data Model terdapat di tiga lokasi pada library keluaran Pagonila.
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.
Daftar endpoint API yang didefinisikan pada API Specification didaftarkan sebagai interface
Typescript dalam namespace Schema
. Misal pada API Specification terdapat data sbb:
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:
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:
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:
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>
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
:
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>
Data schemas
yang terdapat pada API Specification menghasilkan masing-masing interface
dari setiap skema, misal pada contoh berikut:
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;
}
Namespace Schema
yang terdapat pada /driver
sama persis seperti yang dihasilkan
pada /engine
.
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:
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
...
"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