nextjs-turnstile
Version:
Integrate Cloudflare Turnstile CAPTCHA in Next.js applications
146 lines (140 loc) • 6.58 kB
TypeScript
import * as react_jsx_runtime from 'react/jsx-runtime';
/**
* Public props for {@link TurnstileImplicit}.
* All props are optional so you can drop the component in with zero config.
*/
interface TurnstileImplicitProps {
/** Your Cloudflare *site‑key*. If omitted we fall back to
* `process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY`. */
siteKey?: string;
/** Widget theme. `'auto'` follows the user's colour‑scheme. */
theme?: "auto" | "light" | "dark";
/** Widget size. */
size?: "normal" | "compact";
/**
* Name of the hidden input that will receive the token. Must be **unique**
* per page. The same name is also used to build callback identifiers, so
* duplication would clash – we throw if this happens.
*/
responseFieldName?: string;
/** How Turnstile behaves when a token expires. We default to 'auto' as cloudflare recommends. */
refreshExpired?: "auto" | "manual" | "never";
/** How Turnstile behaves when a widget times out. We default to 'auto' as cloudflare recommends. */
refreshTimeout?: "auto" | "manual" | "never";
/** Extra class to apply to the host `<div>` element. */
className?: string;
/** Fires when the widget returns a *valid* token. */
onSuccess?(token: string): void;
/** Fires when the token *expires* (~2 min). */
onExpire?(): void;
/** Fires when the interactive challenge times out. */
onTimeout?(): void;
/** Fires on unrecoverable error. */
onError?(): void;
}
declare function TurnstileImplicit({ siteKey, theme, size, responseFieldName, refreshExpired, refreshTimeout, className, onSuccess, onExpire, onTimeout, onError, }: TurnstileImplicitProps): react_jsx_runtime.JSX.Element;
/** Props for an explicit-mode Turnstile widget. */
interface TurnstileExplicitProps {
/** ID of the div that will contain the widget.
If omitted we generate a unique one so you can mount many widgets. */
containerId?: string;
/** Your public site-key (defaults to `process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY`). */
siteKey?: string;
/** 'auto' picks-up user's colour-scheme. */
theme?: "auto" | "light" | "dark";
/** 'normal' ≈ 300×65, 'compact' ≈ 130×65. */
size?: "normal" | "compact";
/**
* Name of the hidden input that will receive the token. Must be **unique**
* per page. The same name is also used to build callback identifiers, so
* duplication would clash – we throw if this happens.
*/
responseFieldName?: string;
/** How Turnstile behaves when a token expires. We default to 'auto' as cloudflare recommends. */
refreshExpired?: "auto" | "manual" | "never";
/** How Turnstile behaves when a widget times out. We default to 'auto' as cloudflare recommends. */
refreshTimeout?: "auto" | "manual" | "never";
onSuccess?(token: string): void;
onError?(): void;
onExpire?(): void;
onTimeout?(): void;
}
/**
* Renders a Cloudflare Turnstile widget in explicit mode.
*
* This component handles the entire lifecycle of the widget, from loading the
* Turnstile script to rendering the widget and cleaning up on unmount. It is
* designed to be resilient to the complexities of React's rendering lifecycle
* in development environments (like Strict Mode and Fast Refresh).
*
* @param {TurnstileExplicitProps} props - The component's props.
* @see https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#explicitly-render-the-turnstile-widget
*/
declare function TurnstileExplicit({ containerId: customContainerId, siteKey: customSiteKey, theme, size, onSuccess, onError, onExpire, onTimeout, refreshExpired, refreshTimeout, responseFieldName, }: TurnstileExplicitProps): react_jsx_runtime.JSX.Element;
/** Options for verifying a Turnstile token. */
interface VerifyOptions {
/** Override default secret key (falls back to `TURNSTILE_SECRET_KEY`). */
secretKey?: string;
/** Provide IP manually – otherwise we attempt to auto‑detect via `getClientIp()`. */
ip?: string;
/** Optional headers fallback when running in pages router API routes. */
headers?: Record<string, string | string[] | undefined> | Headers;
}
/**
* Verifies a Cloudflare Turnstile token on the server.
*
* ```ts
* const ok = await verifyTurnstile(token);
* if (!ok) throw new Error("Captcha failed");
* ```
*
* @param token - The token returned by the widget.
* @param options - Optional overrides (`secretKey`, `ip`, `headers`).
* @returns Whether the token is valid.
*/
declare function verifyTurnstile(token: string, options?: VerifyOptions): Promise<boolean>;
/** Union of the values users can pass when referring to a widget. */
type WidgetRef = string | number | HTMLElement;
/** Minimal subset of Cloudflare's Turnstile API used by the helpers. */
interface TurnstileAPI {
render(host: WidgetRef, cfg?: Record<string, unknown>): string | number;
reset(widget?: WidgetRef): void;
remove(widget?: WidgetRef): void;
getResponse(widget?: WidgetRef): string | null;
}
declare global {
interface Window {
turnstile?: TurnstileAPI;
}
}
/**
* Returns **true** once `window.turnstile` is available.
*/
declare function isTurnstileLoaded(): boolean;
/**
* Resets a widget by ID / selector so the user can solve it again.
* No‑ops silently on server or if Turnstile isn't loaded.
*/
declare function resetTurnstile(widget?: WidgetRef): void;
/**
* Ensures a widget is rendered
*
* Implementation notes:
* • Cloudflare exposes no standalone `execute()` API like reCAPTCHA. The
* closest is implicit execution: the widget renders automatically on
* elements with `.cf‑turnstile`. To mimic a user's expectation of
* "execute", we attempt to read the response. If `turnstile.getResponse`
* throws (widget not found) **or** returns an empty string, we *render*
* the widget in place and then return `null` so callers can wait for the
* normal `callback` to fire.
*
* @param widget CSS selector, numeric widgetId, or host element.
* @returns Current response token, or `null` if none.
*/
declare function executeTurnstile(widget: WidgetRef): void;
/**
* Returns the current CAPTCHA token for a widget, or **null** if unavailable.
* Wrapper is SSR‑safe and suppresses Turnstile errors.
*/
declare function getTurnstileResponse(widget: WidgetRef): string | null;
export { TurnstileExplicit, TurnstileImplicit, executeTurnstile, getTurnstileResponse, isTurnstileLoaded, resetTurnstile, verifyTurnstile };