refactor(website): Address claude follow-up review on Turnstile pre-mint

- Drop the unused `error` ref from `useTurnstile`. The widget-level
  error-callback writes had no observer (only `usePackRequest.error`
  feeds the UI), so the export and writes were vestigial.
- Drop `getResponse` from `TurnstileGlobal`. Never called anywhere in
  the codebase; clearer to leave it off the typed surface.
- Don't `console.warn` on normal cancel/timeout flows in
  `acquireTurnstileToken`. Move the warn after the `signal.aborted`
  check so the dev console only logs genuine challenge / script-load
  failures.
- Hoist the consecutive `if (widgetId.value)` guards in `mintToken` by
  capturing the rendered widget id into a local const after the throw.
- Drop the redundant `userTouched.value` check in the post-pack
  pre-mint guard. `userTouched` is necessarily true at this point —
  it was a precondition for `isSubmitValid` being true when the submit
  started.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kazuki Yamada
2026-05-05 22:28:33 +09:00
parent 2ee93b3214
commit 2a0922d114
4 changed files with 14 additions and 12 deletions
@@ -26,10 +26,12 @@ export async function acquireTurnstileToken(
try {
return { kind: 'token', token: await turnstile.takeToken(signal) };
} catch (err) {
console.warn('Turnstile token acquisition failed:', err);
// Abort is a normal flow (user cancel, 30s timeout). Don't log it as
// a failure — only log genuine challenge / script-load errors.
if (signal.aborted) {
return { kind: 'aborted', reason: signal.reason };
}
console.warn('Turnstile token acquisition failed:', err);
if (import.meta.env.PROD) {
return { kind: 'error', message: turnstileFailureMessage(err) };
}
+6 -3
View File
@@ -212,9 +212,12 @@ export function usePackRequest() {
// Repeat-pack convenience: warm the cache for a likely follow-up
// submission (option tweak + repack, or `repackWithSelectedFiles`
// triggered from the result view). Skipped on abort/cancel since
// the user may have given up. Failures swallow silently — they
// surface on the next click via takeToken's cold path.
if (!controller.signal.aborted && isSubmitValid.value && userTouched.value) {
// the user may have given up, and on invalid form (user may have
// cleared the URL mid-request). userTouched is necessarily true
// here — it was a precondition for isSubmitValid to be true at
// submit start. Failures swallow silently — they surface on the
// next click via takeToken's cold path.
if (!controller.signal.aborted && isSubmitValid.value) {
turnstile.preMintToken().catch(() => {});
}
}
+5 -7
View File
@@ -32,7 +32,6 @@ const MINT_TIMEOUT_MS = 15_000;
export function useTurnstile() {
const widgetId = ref<string | null>(null);
const containerEl = ref<HTMLElement | null>(null);
const error = ref<string | null>(null);
// Resolved when the next widget callback produces a token. Reassigned on
// every mint so back-to-back submits don't share state.
@@ -99,10 +98,8 @@ export function useTurnstile() {
}
},
'error-callback': (errorCode: string) => {
const message = `Turnstile error: ${errorCode}`;
error.value = message;
if (pendingReject) {
pendingReject(new Error(message));
pendingReject(new Error(`Turnstile error: ${errorCode}`));
pendingResolve = null;
pendingReject = null;
}
@@ -147,7 +144,8 @@ export function useTurnstile() {
throw new Error('Turnstile container element not registered');
}
const turnstile = await ensureWidget(containerEl.value);
if (!widgetId.value) {
const renderedWidgetId = widgetId.value;
if (!renderedWidgetId) {
throw new Error('Turnstile widget failed to render');
}
@@ -182,8 +180,8 @@ export function useTurnstile() {
};
// Tokens are 1-shot, so reset() before each execute() to clear any
// stale challenge state inside the widget itself.
if (widgetId.value) turnstile.reset(widgetId.value);
if (widgetId.value) turnstile.execute(widgetId.value);
turnstile.reset(renderedWidgetId);
turnstile.execute(renderedWidgetId);
});
const timeoutPromise = new Promise<never>((_, reject) => {
@@ -14,7 +14,6 @@ export interface TurnstileGlobal {
execute: (widgetId: string) => void;
reset: (widgetId: string) => void;
remove: (widgetId: string) => void;
getResponse: (widgetId: string) => string | undefined;
}
export interface TurnstileRenderOptions {