
# Referensi CLI

merql menyertakan CLI untuk mengambil snapshot, menghitung perbedaan, dan menjalankan penggabungan langsung dari terminal. Composer memasangnya sebagai `vendor/bin/merql`; dalam checkout repositori merql, namanya adalah `bin/merql`.

`vendor/bin/merql` berfungsi dari instalasi dependensi karena merql 0.4.1. Rilis sebelumnya hanya mencari autoloader Composer di direktori `vendor/` milik paket itu sendiri dan gagal ketika merql dipasang sebagai dependensi.

## Mulai cepat

```bash
# Capture a baseline from your database.
export MERQL_DB_DSN="sqlite:/path/to/db.sqlite"
vendor/bin/merql snapshot base

# Make some changes, then capture again.
vendor/bin/merql snapshot current

# See what changed.
vendor/bin/merql diff base current
```

Penggabungan tiga arah memerlukan ours dan theirs yang diambil dari dua database yang menyimpang dari base. Arahkan `MERQL_DB_DSN` ke database yang tepat untuk setiap snapshot:

```bash
# Base: live before the sandbox was copied from it.
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base

# ... copy live.sqlite to sandbox.sqlite, then both databases change ...

MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs

# Three-way merge with dry-run preview.
vendor/bin/merql merge base ours theirs --dry-run
```

Mengambil ketiga snapshot dari database yang sama secara berurutan tidak dapat digunakan untuk penggabungan: theirs akan sudah memuat perubahan ours, sehingga setiap baris yang disisipkan ours akan dilaporkan sebagai konflik `insert_insert`.

## Variabel lingkungan

CLI membaca detail koneksi database dari variabel lingkungan. Anda dapat
terhubung menggunakan string DSN PDO atau parameter MySQL individual.

### Koneksi berbasis DSN

Gunakan `MERQL_DB_DSN` untuk koneksi berbasis PDO. Ini pendekatan yang disarankan
untuk SQLite dan konfigurasi nonstandar. DSN harus menunjuk ke database MySQL
atau SQLite: CLI tidak dapat mendaftarkan driver untuk mesin lain.

| Variabel | Deskripsi | Contoh |
|---|---|---|
| `MERQL_DB_DSN` | String DSN PDO lengkap | `sqlite:/path/to/db.sqlite` |
| `MERQL_DB_USER` | Nama pengguna (opsional dengan DSN) | `root` |
| `MERQL_DB_PASS` | Kata sandi (opsional dengan DSN) | `secret` |

```bash
# SQLite file.
export MERQL_DB_DSN="sqlite:/var/data/myapp.sqlite"

# MySQL via DSN.
export MERQL_DB_DSN="mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="secret"
```

Gunakan database SQLite berbasis berkas. Setiap perintah CLI berjalan dalam prosesnya sendiri, jadi
`sqlite::memory:` selalu membuka database baru yang kosong dan snapshot darinya
tidak berisi tabel.

### Singkatan MySQL

Jika `MERQL_DB_DSN` tidak disetel, CLI menggunakan variabel khusus MySQL sebagai alternatif.

| Variabel | Default | Deskripsi |
|---|---|---|
| `MERQL_DB_NAME` | (wajib) | Nama database |
| `MERQL_DB_HOST` | `127.0.0.1` | Host MySQL |
| `MERQL_DB_PORT` | `3306` | Port MySQL |
| `MERQL_DB_USER` | `root` | Nama pengguna MySQL |
| `MERQL_DB_PASS` | (kosong) | Kata sandi MySQL |
| `MERQL_DB_ADAPTER` | `pdo` | Setel ke `mysqli` untuk menggunakan adapter mysqli |

```bash
export MERQL_DB_NAME="wordpress"
export MERQL_DB_HOST="127.0.0.1"
export MERQL_DB_PORT="3306"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="password"
```

## Perintah

### `merql snapshot <name>`

Ambil keadaan database saat ini yang namanya ditentukan oleh variabel lingkungan, lalu simpan sebagai snapshot bernama. Ini satu-satunya perintah yang terhubung ke database.

```bash
vendor/bin/merql snapshot baseline
```

Keluaran:

```
Snapshot 'baseline' saved
Tables: posts, comments, users, settings
```

Snapshot disimpan sebagai berkas JSON di `.merql/snapshots/` dalam direktori kerja (lihat [Penyimpanan Snapshot](#snapshot-storage)). Nama hanya boleh berisi karakter alfanumerik, tanda hubung, dan garis bawah.

Alur kerja umum: ambil snapshot sebelum membuat perubahan, lalu ambil snapshot lagi setelahnya. Kedua snapshot menjadi dasar perbandingan atau penggabungan.

### `merql diff <base> <current>`

Bandingkan dua snapshot bernama dan tampilkan ringkasan perbedaannya.

```bash
vendor/bin/merql diff baseline current
```

Keluaran:

```
Changeset: baseline -> current
  Inserts: 3
  Updates: 7
  Deletes: 1
```

Kedua snapshot harus sudah ada (sebelumnya diambil dengan `merql snapshot`). Perbandingan tidak memerlukan koneksi database karena beroperasi pada berkas snapshot yang tersimpan.

### `merql merge <base> <ours> <theirs>`

Lakukan penggabungan tiga arah atas tiga snapshot bernama.

```bash
vendor/bin/merql merge base ours theirs
```

Keluaran:

```
Merge: base + ours + theirs
  Operations: 12
  Conflicts:  0
  Clean:      yes
```

Ketiga snapshot harus sudah ada. Penggabungan tidak memerlukan koneksi database karena beroperasi pada berkas snapshot yang tersimpan, dan tidak pernah menulis ke database: CLI tidak memiliki perintah apply. Gunakan PHP API untuk menerapkan hasil penggabungan.

CLI menggabungkan pada tingkat kolom. Proses ini tidak menerapkan penggabungan tingkat sel pada kolom TEXT atau JSON, jadi dua suntingan berbeda pada kolom yang sama selalu menjadi konflik di sini ([#7](https://github.com/inline0/merql/issues/7)). Gunakan `ThreeWayMerge` dengan `CellMergeConfig` di PHP untuk penggabungan tingkat sel.

#### `--dry-run`

Tambahkan opsi `--dry-run` untuk melihat pratinjau pernyataan SQL yang akan dihasilkan penggabungan tanpa menjalankan apa pun. Pernyataan tersebut menjelaskan cara mengubah keadaan base menjadi hasil gabungan, sehingga mencakup perubahan dari kedua sisi.

```bash
vendor/bin/merql merge base ours theirs --dry-run
```

Keluaran:

```
Merge: base + ours + theirs
  Operations: 3
  Conflicts:  0
  Clean:      yes

Dry run SQL:
  INSERT INTO `posts` (`id`, `title`, `status`) VALUES ('10', 'New Post', 'draft');
  UPDATE `posts` SET `title` = 'Updated Title' WHERE `id` = '5';
  DELETE FROM `comments` WHERE `id` = '3';
```

## Perintah pengembangan

Checkout repositori merql memiliki lebih banyak skrip di `bin/` untuk rangkaian pengujian berbasis oracle. Skrip tersebut bukan bagian dari paket Composer, jadi instalasi dependensi hanya memiliki `vendor/bin/merql`. Jalankan dari akar repositori setelah `composer install`.

| Perintah | Deskripsi |
|---|---|
| `./bin/oracle <name>` | Hitung hasil penggabungan yang diharapkan untuk suatu skenario |
| `./bin/actual <name>` | Jalankan merql pada suatu skenario dan ambil keluarannya |
| `./bin/compare <name>` | Bandingkan keluaran oracle dengan keluaran aktual |
| `./bin/test-scenario <name>` | Pipeline lengkap: penyiapan, oracle, aktual, perbandingan |
| `./bin/test-regression` | Jalankan semua skenario |
| `./bin/test-regression --category clean` | Jalankan satu kategori: `clean`, `conflict`, `identity`, `types`, `scale`, atau `edge` |
| `./bin/test-regression --fast` | Hanya lulus/gagal, tanpa laporan |
| `./bin/verify-compliance` | Laporan kepatuhan lengkap |
| `./bin/verify-all` | PHPStan + gaya kode + PHPUnit + regresi oracle |

`bin/test-regression` juga menerima `--jobs`, tetapi saat ini mengabaikan nilainya dan menjalankan skenario satu per satu ([#5](https://github.com/inline0/merql/issues/5)). `--category` yang tidak dikenal menampilkan `No scenarios found` dan keluar dengan sukses.

Lihat [Strategi Pengujian](https://merql.inline0.dev/id/docs/advanced/testing) untuk tata letak skenario.

## Status keluar

`merql snapshot`, `diff`, dan `merge` keluar dengan status 1 jika argumen tidak ada, dan `snapshot` juga demikian jika koneksi belum dikonfigurasi. Snapshot yang tidak ditemukan membuat perintah berakhir dengan `SnapshotException` yang tidak tertangani dan status bukan nol. Perintah yang tidak dikenal menampilkan `Unknown command` tetapi saat ini keluar dengan status 0 ([#3](https://github.com/inline0/merql/issues/3)).

## Penyimpanan Snapshot

Snapshot disimpan di `.merql/snapshots/` relatif terhadap direktori kerja. Setiap snapshot berupa satu berkas JSON bernama `<name>.json`. Jalankan semua perintah dari direktori yang sama agar masing-masing dapat menemukan snapshot lainnya.

CLI tidak memiliki opsi atau variabel lingkungan untuk lokasi lain ([#8](https://github.com/inline0/merql/issues/8)). Untuk menggunakan lokasi lain, pindah ke direktori kerja yang berbeda sebelum menjalankannya. Di PHP, tetapkan direktori sebelum mengambil atau memuat snapshot:

```php
use Merql\Snapshot\SnapshotStore;

SnapshotStore::setDirectory('/var/data/merql-snapshots');
```

Berkas snapshot bersifat portabel. Anda dapat menyalinnya antar mesin, memasukkannya ke kontrol versi, atau membagikannya untuk debugging kolaboratif. Snapshot yang diambil oleh CLI dapat dimuat di PHP dengan `SnapshotStore::load()`, dan sebaliknya, selama keduanya menggunakan direktori yang sama.
