Bash: Membuat Generator File dengan Template
Sering kali kita menulis hal yang berulang misalnya ketika membuat file baru dan isinya mirip-mirip saja, sebenarnya hal itu dapat diakali dengan membuat sebuah generator. Kenapa generator? ya karena “hal yang berulang” bisa kita jadikan sebuah template dan hanya mengganti atau menambahkan beberapa hal yang sifatnya dinamis.
Kasus dan Persiapan
Kasus sederhana yang saya alami belakangan adalah file migration untuk database yang isinya mirip kecuali di beberapa bagian.
Di sini kita akan membuat tiga file dan dibungkus dalam sebuah folder scripts
, yaitu:
migration.sh
sebagai file utama atau entrypointfunctions.sh
file untuk menyimpan fungsi-fungsicreate.template.ts
template yang akan kita gunakan
Template file migration dengan $TABLE_NAME
sebagai variabel yang nantinya bisa diganti dengan nilai lain.
import { Kysely, sql } from 'kysely';
const tableName = '$TABLE_NAME';
export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable(tableName)
.addColumn('id', 'uuid', (col) =>
col.primaryKey().defaultTo(sql`gen_random_uuid()`)
)
.execute();
}
export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable(tableName).execute();
}
Kenapa menggunakan bash
? Saya pikir karena tugasnya sederhana jadi bash
saja sudah cukup.
Membuat Generator
File utama untuk menjalankan perintah migrasi memiliki opsi perintah yang diambil dari argumen ketika mengeksekusi file ini (di sini hanya create
dan *
). Opsi *
bisa dibaca sebagai semua perintah
atau dalam kasus algoritma ini bisa dibaca sebagai else
, default
atau sejenisnya.
Nilai $1
diambil dari parameter kedua, $2
parameter ketiga, dan seterusnya menyesuaikan index
ketika mengeksekusi sebuah file. Contohnya ketika mengeksekusi file:
./migration.sh create
./migration.sh
sebagai parameter pertama ($0
) sedangkan create
sebagai parameter kedua ($1
).
Fungsi create_migration_with_template
yang diimport dari file functions.sh
dipanggil dengan argumen $file_name
dan $table_name
.
Note: ada tambahan opsi (walaupun belum rapi)
-t
untuk memberi nama tabel di migration. Kenapa tidak memakaigetops
? Sudah dicoba tetapi agak ribet di struktur kode yang saya buat ini, jadi saya akali saja sementara.
#!/usr/bin/env sh
. scripts/functions.sh
create(){
if [ -z "$2" ]; then
echo "Error: Please provide a file name."
echo "Usage: $0 create <file_name> [-t] <table_name>"
exit 1
fi
file_name="$2"
table_name="$2"
echo "Creating migration file for '$file_name'..."
if [ "$3" = "-t" ] && [ -n "$4" ]; then
table_name="$4"
fi
create_migration_with_template "$file_name" "$table_name"
}
case $1 in
'create')
create "$@"
;;
*)
echo "Usage: $0 { create table_name }"
;;
esac
File functions.sh
menyimpan fungsi-fungsi yang akan digunakan dan dipanggil di file utama. Kenapa dipisah? agar rapi saja (menurut saya).
Mengganti variabel pada template yang telah kita buat dengan menulis perintah sed “s|\$TABLE_NAME|$table_name|g”
yang artinya mengganti string dengan nilai $TABLE_NAME
dengan nilai dari variable $table_name
.
#!/usr/bin/env sh
migration_output_path="libs/api/database/src/lib/migrations"
migration_template_create_path="scripts/templates/create.template.ts"
create_migration_with_template() {
file_name="$1"
table_name="$2"
migration_file="$migration_output_path/$(date '+%Y_%m_%d_%H%M%S')_$file_name.ts"
template_content=$(cat "$migration_template_create_path")
content_with_variable=$(echo "$template_content" | sed "s|\$TABLE_NAME|$table_name|g")
echo "$content_with_variable" > "$migration_file"
echo "Migration file for '$1' created successfully!"
echo "Path: $migration_file"
}
Karena contoh project ini ada di ekosistem Javascript / Typescript jadi kita bisa definisikan perintah di package.json
pada properti scripts
untuk mempermudah atau mempersingkat perintah yang akan dijalankan.
{
"scripts": {
"migrate:create": "./scripts/migration.sh create"
}
}
Jadi untuk membuat file migration kita dapat menjalankan perintah berikut (contoh dengan pnpm
):
pnpm migrate:create <file_name> -t <table_name>
OR
pnpm migrate:create <table_name|file_name>
Catatan
Mungkin ada yang tidak bisa menjalankan program bash
tersebut karena tidak memiliki hak akses untuk dieksekusi sebagai sebuah program, solusinya adalah dengan menjalankan perintah berikut untuk memberi hak akses eksekusi (executeable) semua file di folder scripts
.
sudo chmod +x ./scripts/*
Penutup
Jadi begitulah contoh pembuatan generator file dengan template menggunakan bash
, ini hanya tulisan iseng karena saya sedang tidak ada task di kerjaan saya, hehe. Tulisan selanjutnya akan berfokus pada CI/CD, DevOps, Deployment, Infrastructure menggunakan repository atau project di atas.
Terima kasih