5
Mode Rewrite dan Status API
Mode --rewrite adalah satu-satunya jalur di src/build.ts yang memperbarui status setiap entri API. Tanpa flag ini build hanya menyusun ulang Markdown. Dengan flag ini, setiap documentationUrl di-crawl, status diperbarui, dan entri yang mati atau mengandung kata blacklist dibuang dari berkas datanya. Flag dibaca langsung dari Bun.argv[2], sedangkan nilai status lama disimpan lebih dulu di variabel previous (src/build.ts:20-231). Penyusunan Markdown setelah loop ini dibahas di Pipeline Build Markdown.
Tiga keadaan status
Field status bertipe boolean dan wajib ada pada setiap ItemType, bersama documentationUrl yang juga wajib (src/types.ts:1-82). Selama crawl nilainya hanya true atau false (src/build.ts:483). Namun daftar punya tiga keadaan akhir, karena false yang bertahan dua kali berturut-turut dihapus dari array.
stateDiagram-v2
state "status true — tetap di daftar" as Aktif
state "status false — nonaktif sementara" as Nonaktif
state "entri dihapus lewat json.apis.splice" as Dihapus
[*] --> Aktif
[*] --> Nonaktif
Aktif --> Aktif: respons bukan 404
Aktif --> Nonaktif: respons 404 atau fetch gagal
Nonaktif --> Aktif: crawl berikutnya bukan 404
Nonaktif --> Dihapus: api.status false dan previous false
Aktif --> Dihapus: crawledx mengandung url
Dihapus --> [*]
classDef sehat fill:#2d7d46,color:#fff
classDef ragu fill:#f59e0b,color:#000
classDef bahaya fill:#dc2626,color:#fff
class Aktif sehat
class Nonaktif ragu
class Dihapus bahaya
%% fig: Transisi status entri API pada mode rewrite
%% desc: Status berpindah antara true dan false di setiap crawl, lalu entri dihapus ketika gagal dua kali berturut-turut atau memuat kata blacklist.Nilai status baru tidak diukur dari kode 200. Baris api.status = response!.status !== 404 menganggap semua respons selain 404 sebagai hidup, termasuk 401, 403, dan 500 (src/build.ts:483). Kalau fetch melempar error — DNS gagal, timeout 10 detik, atau redirect terlalu banyak — status menjadi false dan log tetap menulis label [ 404 ] meski penyebabnya bukan 404 (src/build.ts:55-584).
Cache per URL dan parameter fetch
crawled adalah Record<string, boolean> yang berfungsi sebagai cache untuk satu kali jalan, bersama satu https.Agent yang dipakai ulang (src/build.ts:9-105). Kuncinya adalah url hasil api.documentationUrl.split('#')[0], jadi anchor #... tidak membedakan entri (src/build.ts:306). Kalau URL sudah ada di cache, status diambil dari cache tanpa request baru (src/build.ts:32-347). Hasil crawl baru ditulis ke cache setelah blok try/catch selesai (src/build.ts:60-618).
Cache ini tidak pernah disimpan ke disk. Ia hanya hidup selama proses, sehingga setiap run --rewrite memulai crawl dari nol.
graph TD
Flag["bun start --rewrite"] --> Load["getFiles lalu Bun.file(file).json()"]
Load --> Check{"documentationUrl ada?"}
Check -->|tidak| Exit["documentationUrl is required. lalu process.exit(1)"]
Check -->|ada| Norm["url = documentationUrl.split('#')[0]"]
Norm --> Cache{"url in crawled"}
Cache -->|ya| Hit["api.status = crawled[url]"]
Cache -->|tidak| Fetch["fetch dengan AbortSignal.timeout(10_000)"]
Fetch --> Status{"response.status !== 404"}
Status -->|ya| Live["api.status = true"]
Status -->|tidak| Dead["api.status = false"]
Fetch -->|throw| Dead
Live --> Nsfw["isBlacklisted(body) lalu crawledx.push(url)"]
Nsfw --> Store["crawled[url] = api.status"]
Dead --> Store
Hit --> Hapus{"crawledx.includes(url) atau api.status false dan previous false"}
Store --> Hapus
Hapus -->|ya| Splice["json.apis.splice(i, 1) lalu i--"]
Hapus -->|tidak| Write["Bun.write(file, JSON.stringify(json, undefined, 2))"]
Splice --> Write
style Flag fill:#f59e0b,color:#000
style Cache fill:#8b5cf6,color:#fff
style Hit fill:#8b5cf6,color:#fff
style Store fill:#8b5cf6,color:#fff
style Live fill:#2d7d46,color:#fff
style Dead fill:#dc2626,color:#fff
style Exit fill:#dc2626,color:#fff
style Splice fill:#dc2626,color:#fff
style Nsfw fill:#dc2626,color:#fff
style Write fill:#336791,color:#fff
%% fig: Alur satu entri API di dalam mode rewrite
%% desc: Setiap entri melewati cache URL, fetch dengan timeout 10 detik, penentuan status, penandaan NSFW, lalu pemeriksaan penghapusan sebelum berkas ditulis.Opsi fetch dipilih agar situs pemerintah dan layanan lama tetap bisa diperiksa:
| Opsi | Nilai | Efek |
|---|---|---|
headers | { 'Accept-Encoding': 'zlib, gzip' } | body diminta dalam bentuk terkompresi |
agent | new https.Agent({ rejectUnauthorized: false }) | sertifikat TLS yang tidak valid tidak menggagalkan crawl |
redirect | 'follow' | redirect diikuti otomatis |
follow | 10 | maksimal 10 lompatan redirect |
signal | AbortSignal.timeout(10_000) | satu request dibatasi 10 detik |
Seluruh opsi itu ditulis pada satu pemanggilan fetch yang sama (src/build.ts:39-459), dan agent didefinisikan sekali di tingkat modul (src/build.ts:9-105).
Setiap cabang meninggalkan jejak di log dengan prefix yang berbeda:
| Prefix log | Arti | Sumber |
|---|---|---|
[ ... ] | request dimulai, URL belum ada di cache | src/build.ts:3710 |
[ <status> ] | respons diterima, kode HTTP hasil crawl dicetak | src/build.ts:46-4911 |
[ cache ] | URL sudah dicek pada run ini, tidak ada request | src/build.ts:32-347 |
[ 404 ] | fetch melempar error; label ini dipakai untuk semua error, bukan hanya 404 | src/build.ts:55-584 |
Aturan penghapusan
Setelah status diperbarui, dua kondisi diperiksa dengan operator OR dalam satu blok if (src/build.ts:64-6912):
| Kondisi | Kapan bernilai benar | Sumber |
|---|---|---|
crawledx.includes(url) | body respons memuat salah satu kata blacklist | src/build.ts:51-5413 |
!api.status && !previous | respons kali ini dan status sebelumnya sama-sama false | src/build.ts:64-6912 |
crawledx hanya diisi lewat isBlacklisted(body) (src/build.ts:51-5413). Fungsi itu mengembalikan true jika body memuat salah satu item daftar (src/utils/index.ts:35-3714), dan daftar saat ini berisi tiga kata: nfsw, porn, hentai (src/data/blacklist.json:115). Cara kerja filter ini dirinci di Helper Berkas dan Filter Blacklist.
Entri yang lolos kedua kondisi tetap di array. Entri yang kena dihapus dengan json.apis.splice(i, 1) lalu i-- agar indeks berikutnya tidak terlewat (src/build.ts:71-7216). Hasil akhir setiap berkas ditulis balik ke disk dengan indentasi 2 spasi (src/build.ts:7717).
⚠️ Panduan kontribusi menjanjikan pengecekan berbasis kode 200: bulan pertama bukan 200 maka status dinonaktifkan sementara, bulan kedua masih bukan 200 maka URL dihapus (CONTRIBUTING.md:58-6618). Kode memakai
!== 404(src/build.ts:483). Akibatnya halaman yang membalas 401, 403, atau 500 tetap berstatustruedan tidak pernah masuk jalur penghapusan.
⚠️
--rewritebersifat destruktif. Berkas di direktoridata/ditulis ulang di tempat (src/build.ts:7717) dan tidak ada mode dry-run. Bila satu entri saja tidak punyadocumentationUrl,process.exit(1)menghentikan seluruh proses (src/build.ts:25-2819) sehingga crawl dan penulisan sisa berkas tidak selesai.
Menjalankan mode rewrite
Script start meneruskan argumen tambahan ke src/build.ts, jadi bun start --rewrite adalah bentuk yang dipakai (package.json:3920). Workflow Update Status menjalankan perintah yang sama lalu membuat commit, pada jadwal bulanan 0 0 1 * * (.github/workflows/update-status.yml:5-621). Langkah pemanggilannya ada di .github/workflows/update-status.yml:25-2622. Detail jadwal, versi Bun, dan langkah commit dibahas di Otomasi GitHub Actions; untuk menjalankan build tanpa flag, lihat Menjalankan Proyek di Lokal.