fix(clickclack): clear deadcode and lint breaks in setup flow

Recent setup commits left the hard-zero gates red on every PR:
parseClickClackSetupCodeInput was exported but only used internally,
ClickClackSetupCodeClaimError was exported yet consumed only by its
test (production catches it structurally through a status field), a
string spread tripped no-misused-spread, and a computed "token" key
tripped no-useless-computed-key. Un-export both symbols, switch the
test to a structural claim-error stand-in matching what the formatter
reads, and apply the two mechanical lint fixes.
This commit is contained in:
Peter Steinberger
2026-07-16 16:23:24 -07:00
parent 23de5c297d
commit d6026ff1fa
3 changed files with 12 additions and 11 deletions

View File

@@ -13,7 +13,7 @@ const CLICKCLACK_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
const CLICKCLACK_SETUP_CODE_CLAIM_JSON_LIMIT_BYTES = 64 * 1024;
const CLICKCLACK_SETUP_CODE_CLAIM_TIMEOUT_MS = 30_000;
export class ClickClackSetupCodeClaimError extends Error {
class ClickClackSetupCodeClaimError extends Error {
constructor(
readonly status: number,
detail: string,

View File

@@ -14,13 +14,18 @@ vi.mock("./setup-claim.js", async (importOriginal) => ({
vi.mock("./setup-verify.js", () => ({
verifyClickClackAccountAfterSetup,
}));
import { ClickClackSetupCodeClaimError } from "./setup-claim.js";
import {
applyClickClackCredentialConfig,
clickClackSetupAdapter,
normalizeClickClackBaseUrl,
} from "./setup-core.js";
// Structural stand-in for the internal claim error: the setup formatter
// duck-types on a numeric `status`, so tests need only that shape.
function makeClaimError(status: number, detail: string): Error {
return Object.assign(new Error(`claim failed (${status}): ${detail}`), { status });
}
function validate(params: {
cfg?: OpenClawConfig;
accountId?: string;
@@ -163,16 +168,12 @@ describe("ClickClack setup adapter", () => {
});
it("maps invalid and rate-limited claims to actionable errors", async () => {
claimClickClackSetupCode.mockRejectedValueOnce(
new ClickClackSetupCodeClaimError(404, "not found"),
);
claimClickClackSetupCode.mockRejectedValueOnce(makeClaimError(404, "not found"));
await expect(
prepare({ code: "ABCD-EFGH-JKMN", baseUrl: "https://clickclack.example" }),
).rejects.toThrow("invalid, expired, or already used");
claimClickClackSetupCode.mockRejectedValueOnce(
new ClickClackSetupCodeClaimError(429, "retry later"),
);
claimClickClackSetupCode.mockRejectedValueOnce(makeClaimError(429, "retry later"));
await expect(
prepare({ code: "ABCD-EFGH-JKMN", baseUrl: "https://clickclack.example" }),
).rejects.toThrow("Too many ClickClack setup code attempts");

View File

@@ -42,7 +42,7 @@ function normalizeClickClackSetupCode(value: string): string | undefined {
const normalized = value.trim().toUpperCase().replaceAll("-", "").replaceAll(" ", "");
if (
normalized.length !== SETUP_CODE_LENGTH ||
[...normalized].some((character) => !SETUP_CODE_ALPHABET.includes(character))
Array.from(normalized).some((character) => !SETUP_CODE_ALPHABET.includes(character))
) {
return undefined;
}
@@ -57,7 +57,7 @@ function requireHttpsClickClackBaseUrl(value: string | undefined): string {
return baseUrl;
}
export function parseClickClackSetupCodeInput(params: { code: string; baseUrl?: string }): {
function parseClickClackSetupCodeInput(params: { code: string; baseUrl?: string }): {
code: string;
baseUrl: string;
} {
@@ -263,7 +263,7 @@ export const clickClackSetupAdapter: ChannelSetupAdapter = {
return {
...remainingInput,
baseUrl: setup.baseUrl,
["token"]: claim.token,
token: claim.token,
workspace: claim.workspace.id,
...(claim.defaults.defaultTo !== undefined ? { defaultTo: claim.defaults.defaultTo } : {}),
...(claim.defaults.allowFrom !== undefined