chore(tooling): add lint/format gates, pin the toolchain, enforce commit checks
Adds the frontend's first linter and formatter — the Rust half has had cargo fmt --check and clippy in CI for a while, while 274 TS/Svelte files had only svelte-check. ESLint runs clean; 159 findings are recorded as warnings rather than suppressed, so the backlog is visible without painting CI red. Also: `bun run test` no longer drops into watch mode (the "Before Committing" list told people to run a command that never returns), the traceability ratchet moves 82% -> 88%, a pre-commit hook enforces the fast half of that list instead of relying on memory, the dead webdriverio e2e suite and its five devDeps are removed, and the Rust toolchain is pinned to 1.97.1 so the developer machine and the CI builder image stop being five releases apart. TRACES: | DR-205, DR-206, DR-207
This commit is contained in:
@@ -66,6 +66,9 @@
|
||||
|
||||
// Recompute when the reserved bottom gap changes (mini-player shows/hides).
|
||||
$effect(() => {
|
||||
// Bare read: registers `bottomGap` as a dependency of this effect. Svelte 5
|
||||
// idiom, not a stray expression.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
bottomGap;
|
||||
measure();
|
||||
});
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
// A new item in the same slot (scrolling a virtualised list, switching series)
|
||||
// must drop the previous item's optimistic state or it shows the wrong tick.
|
||||
$effect(() => {
|
||||
// Bare read: registers `itemId` as a dependency of this effect. Svelte 5
|
||||
// idiom, not a stray expression.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
itemId;
|
||||
optimistic = null;
|
||||
});
|
||||
|
||||
@@ -263,7 +263,6 @@ export class Html5PlayerAdapter implements PlayerAdapter {
|
||||
timeoutMs: number
|
||||
): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
const done = (fired: boolean) => {
|
||||
el.removeEventListener(event, listener);
|
||||
clearTimeout(timer);
|
||||
@@ -271,7 +270,9 @@ export class Html5PlayerAdapter implements PlayerAdapter {
|
||||
};
|
||||
const listener = () => done(true);
|
||||
el.addEventListener(event, listener);
|
||||
timer = setTimeout(() => done(false), timeoutMs);
|
||||
// `done` closes over `timer`, but can only run once the listener fires or
|
||||
// the timeout elapses — both strictly after this assignment.
|
||||
const timer: ReturnType<typeof setTimeout> = setTimeout(() => done(false), timeoutMs);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export async function getDeviceId(): Promise<string> {
|
||||
return deviceId;
|
||||
} catch (e) {
|
||||
log.error("Failed to get device ID from backend:", e);
|
||||
throw new Error("Failed to initialize device ID: " + String(e));
|
||||
throw new Error("Failed to initialize device ID: " + String(e), { cause: e });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ async function handleStateChanged(state: string, _mediaId: string | null): Promi
|
||||
switch (state) {
|
||||
case "playing":
|
||||
case "paused":
|
||||
case "loading":
|
||||
case "loading": {
|
||||
// When local playback starts, ensure mode is set to local
|
||||
const mode = get(playbackMode);
|
||||
if (mode.mode !== "local") {
|
||||
@@ -236,9 +236,10 @@ async function handleStateChanged(state: string, _mediaId: string | null): Promi
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "idle":
|
||||
case "stopped":
|
||||
case "stopped": {
|
||||
player.setIdle();
|
||||
// When local playback stops, revert to idle mode
|
||||
const currentMode = get(playbackMode);
|
||||
@@ -248,6 +249,7 @@ async function handleStateChanged(state: string, _mediaId: string | null): Promi
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface InvokeCall {
|
||||
}
|
||||
|
||||
let invokeHistory: InvokeCall[] = [];
|
||||
let invokeResponses: Map<string, any> = new Map();
|
||||
const invokeResponses: Map<string, any> = new Map();
|
||||
|
||||
/**
|
||||
* Mock invoke function that captures calls
|
||||
|
||||
@@ -79,7 +79,7 @@ export function validateUrlPathSegment(segment: string): void {
|
||||
}
|
||||
|
||||
// Reject path separators and null bytes
|
||||
if (/[\/\\%]/.test(segment)) {
|
||||
if (/[/\\%]/.test(segment)) {
|
||||
throw new Error("Invalid path segment: contains invalid characters");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user