From 2a0922d1141670d534826589d49ecf8a3094d666 Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Tue, 5 May 2026 22:28:33 +0900 Subject: [PATCH] refactor(website): Address claude follow-up review on Turnstile pre-mint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- website/client/composables/turnstileSubmit.ts | 4 +++- website/client/composables/usePackRequest.ts | 9 ++++++--- website/client/composables/useTurnstile.ts | 12 +++++------- website/client/composables/useTurnstileScript.ts | 1 - 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/website/client/composables/turnstileSubmit.ts b/website/client/composables/turnstileSubmit.ts index 4a27ee3c..8b2fdc39 100644 --- a/website/client/composables/turnstileSubmit.ts +++ b/website/client/composables/turnstileSubmit.ts @@ -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) }; } diff --git a/website/client/composables/usePackRequest.ts b/website/client/composables/usePackRequest.ts index c9b5d9fc..97d45769 100644 --- a/website/client/composables/usePackRequest.ts +++ b/website/client/composables/usePackRequest.ts @@ -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(() => {}); } } diff --git a/website/client/composables/useTurnstile.ts b/website/client/composables/useTurnstile.ts index 13f2d8fd..74c27b42 100644 --- a/website/client/composables/useTurnstile.ts +++ b/website/client/composables/useTurnstile.ts @@ -32,7 +32,6 @@ const MINT_TIMEOUT_MS = 15_000; export function useTurnstile() { const widgetId = ref(null); const containerEl = ref(null); - const error = ref(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((_, reject) => { diff --git a/website/client/composables/useTurnstileScript.ts b/website/client/composables/useTurnstileScript.ts index fc9b7089..d76236be 100644 --- a/website/client/composables/useTurnstileScript.ts +++ b/website/client/composables/useTurnstileScript.ts @@ -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 {