Caputchin
Referensi

Metode dan event widget

Widget Caputchin mengirim dua elemen kustom, dan halamanmu berinteraksi dengannya dalam dua arah: kamu memanggil metode pada elemen untuk mengemudikannya, dan kamu mendengarkan event yang ia pancarkan untuk bereaksi. Halaman ini adalah referensi menyeluruh untuk kedua permukaan.

Setiap event adalah CustomEvent yang dikirim dengan bubbles: true dan composed: true, jadi ia lolos dari shadow DOM widget dan kamu bisa mendengarkannya langsung pada elemen (atau pada leluhur mana pun). Datanya selalu di event.detail.

Dua elemen sekilas

ElemenTujuanMetode
<caputchin-widget>Hanya verifikasi (proof-of-work / checkbox).start()
<caputchin-game>Host game, dengan verifikasi opsional.pass(), fail()

Widget checkbox hanya punya start(); ia tak memaparkan pass() / fail(). Host game tak punya start() (rondenya menjadi hidup saat mount untuk inline, atau pada pembukaan dialog pertama untuk modal / fullscreen). Kedua elemen memancarkan start, pass, error, dan degraded; host game tambahan memancarkan dialog-shown dan dialog-hidden. Cakupan ada di tabel event di bawah.

Metode

start() (hanya <caputchin-widget>)

Memulai verifikasi seketika. Tujuannya adalah pemicu manual: saat elemen punya trigger="manual", kamu memanggil start() untuk menembakkan pemecahan proof-of-work dari gesturmu sendiri (misalnya, saat submit formulirmu) alih-alih checkbox bawaan. Dengan pemicu auto / click baku elemen menyambung aktivasinya sendiri, jadi kamu tak memanggil ini.

const widget = document.querySelector("caputchin-widget");
widget.start();

Host game tak punya start(). Lihat mode manual untuk panduan mengemudikan-sendiri lengkapnya.

pass(payload) (hanya <caputchin-game>)

Melepaskan gerbang verifikasi: pengunjung berhasil. Sah hanya saat trigger="manual"; memanggilnya pada game non-manual memancarkan error dengan kode invalid-call. pass() pertama menebus dan mengunci vonis; panggilan berikutnya diabaikan diam-diam (satu ronde per sesi).

const widget = document.querySelector("caputchin-game");
widget.pass({ trace: roundRecord });
Bidang payloadTipeMakna
tracestringCatatan ronde opaque yang dihasilkan game-mu. Pada ronde bergerbang server memutarnya-ulang untuk menurunkan vonis otoritatif; pada key tak-bergerbang atau hanya-game ia diterima apa adanya. Lewatkan string kosong jika interaksimu tak punya catatan untuk diputar-ulang.

Tak ada bidang score pada metode ini, gerbang adalah putar-ulang trace server, bukan skor yang diklaim-klien. (Sebuah score memang muncul di event pass, yang adalah widget melaporkan kembali ke kamu, bukan kamu ke widget.)

Memanggil pass() sebelum ronde dimulai (modal / fullscreen, dialog belum dibuka) memancarkan error dengan kode invalid-call. Pada key hanya-game (tanpa sitekey) tak ada gerbang untuk dilepaskan, jadi pass() sekadar memancarkan event pass dengan token: null.

fail(payload?) (hanya <caputchin-game>)

Membatalkan ronde: kekalahan definitif. Sah hanya saat trigger="manual" (kalau tidak invalid-call). Opsional, ronde yang tak selesai diperlakukan sebagai non-lolos toh. Ia membatalkan verifikasi yang sedang berlangsung (pemeriksaan proof-of-work dan instrumentasi) dan memunculkan event error dengan kode game-error-relayed.

widget.fail({ code: "out-of-moves", message: "no moves left" });
Bidang payloadTipeMakna
codestring (opsional)Kode diagnostikmu; dimunculkan sebagai originalCode event error. Default ke game-failed.
messagestring (opsional)Alasan yang bisa-dibaca-manusia.

Event

Dengarkan dengan addEventListener(type, handler). Setiap payload hidup di event.detail.

EventDipancarkan olehevent.detailMenyala saat
startkeduanya{ gameId: string | null }Verifikasi dimulai (auto saat mount, saat aktivasi, atau lewat start()). gameId disetel untuk ronde game, null untuk widget biasa.
passkeduanya{ token: string | null, score: number | null, durationMs: number | null }Verifikasi dilepaskan. token adalah token terbungkus untuk dikirim ke backend-mu; null pada key hanya-game (tanpa sitekey).
errorkeduanya{ code, message, severity, originalCode? }Apa pun dari peringatan config benign hingga kegagalan keras. Lihat event error.
degradedkeduanya{ reason: "timeout" | "network" | "http" | "malformed" }Widget tak bisa menyelesaikan ukuran / skin / locale yang kamu konfigurasi tepat waktu, jadi ia merender dengan nilai default bawaannya. Bukan sebuah galat. Lihat event degraded.
dialog-shown<caputchin-game>{ layout: "modal" | "fullscreen" }Sebuah dialog game overlay terbuka (programatik atau klik pertama).
dialog-hidden<caputchin-game>{ layout: "modal" | "fullscreen" }Sebuah dialog game overlay tertutup (programatik, Escape, atau klik latar).

Event pass dan token

Event pass adalah isyaratmu bahwa verifikasi berhasil, tapi ia bukan keputusan kepercayaan. Keputusan kepercayaan adalah backend-mu yang memastikan detail.token. Selalu verifikasi token di backend-mu; jangan pernah memberi akses dari event front-end saja. Di sebuah formulir, widget juga menyuntikkan token sebagai field caputchin-token agar POST formulir biasa membawanya. score dan durationMs pada event ini adalah analitik yang dilaporkan-klien dan bisa null; jangan pernah memperlakukannya sebagai sinyal kepercayaan.

Event error

Event error membawa code stabil, message manusia, sebuah severity, dan kadang originalCode. Tiap kode punya severity default tetap agar kamu bisa menyaring peringatan "tetap berjalan" dari kegagalan "benar-benar rusak" tanpa mengeraskan-kode tabel kode-ke-severity, sekadar baca detail.severity. Set kode penuhnya:

codeseverityMakna
invalid-configwarnSebuah atribut atau kombinasi yang ditolak widget; ia merosot dengan anggun dan tetap berjalan.
invalid-callwarnSebuah metode dipanggil saat ia tak sah (mis. pass() pada game non-manual, atau sebelum ronde dimulai).
verification-failederrorPemeriksaan proof-of-work atau instrumentasi (atau penebusan token) gagal; tak ada token diterbitkan.
game-load-failederrorBundel game tak bisa diselesaikan, dimuat, atau didaftarkan.
gate-unavailableerrorServer mengembalikan penolakan otoritatif saat bootstrap (key bergerbang tak bisa menyuplai game yang sah).
game-error-relayederrorSebuah galat muncul dari dalam game (diteruskan dari iframe, atau dari fail() manual).

detail.originalCode hadir saat code publik adalah generalisasi dari alasan internal yang lebih spesifik (misalnya, kegagalan muatan iframe yang diteruskan sebagai game-load-failed membawa iframe-load-failed / iframe-script-blocked / game-not-registered mentah di originalCode). Pakai code untuk percabangan dan originalCode hanya untuk diagnostik.

Event degraded

Saat mount, widget membuat satu panggilan pendek ke Caputchin untuk menyelesaikan ukuran, skin, dan locale yang kamu konfigurasi (dan, untuk game marketplace, jejak pilihannya). Jika panggilan itu gagal atau terlalu lambat, widget tak memblokir atau patah: ia merender dengan nilai yang dipanggang ke dalam bundel dan memancarkan degraded agar fallback tak pernah senyap. Widget tetap sepenuhnya berfungsi setelah event degraded, hanya presentasi terselesaikan yang mungkin berbeda dari yang kamu konfigurasi (sebuah game mungkin muncul pada ukuran defaultnya, atau checkbox dalam tema defaultnya). Widget mencoba ulang resolusi yang lambat sebelum jatuh ke fallback, jadi degraded berarti percobaan habis, bukan satu percobaan yang lambat.

detail.reason memberitahumu kenapa resolusi jatuh ke fallback, agar kamu bisa memunculkannya di telemetrimu sendiri:

reasonMakna
timeoutResolusi tak menjawab dalam anggaran waktunya (layanan lambat atau tak terjangkau).
networkPermintaan itu sendiri gagal (luring, DNS, terblokir, atau koneksi disetel-ulang).
httpLayanan menjawab dengan status galat.
malformedLayanan menjawab, tapi badannya tak sah.

degraded adalah pemberitahuan, bukan kegagalan, jadi ia sengaja bukan event error: resolusi lambat tak seharusnya memicu handler yang kamu kabelkan untuk kegagalan nyata. Dengarkan ia hanya jika kamu mau mengamati render terdegradasi, misalnya untuk memberi peringatan saat pengunjungmu melihat presentasi fallback.

Mendengarkan, dalam praktik

const widget = document.querySelector("caputchin-game");

const onPass = (e) => {
  // send e.detail.token to your backend to verify
};
const onError = (e) => {
  if (e.detail.severity === "error") {
    console.error(e.detail.code, e.detail.message);
  }
};

widget.addEventListener("pass", onPass);
widget.addEventListener("error", onError);

// Clean up when you tear down your view:
widget.removeEventListener("pass", onPass);
widget.removeEventListener("error", onError);

Ini adalah CustomEvent DOM native, jadi di React kamu melekatkannya dengan ref dan addEventListener (bukan prop JSX onPass); contoh frontend menunjukkan penyambungan spesifik-framework. Karena setiap event menggelembung dan ter-compose, kamu juga bisa mendelegasikan dari elemen kontainer ketimbang mengikat tiap widget satu per satu.

Lihat juga

Di halaman ini