fix(client): correct prettier endOfLine and oxlint disable directives

The Client Typecheck & Test CI job was failing on the prettier format
check. Two real root causes, fixed properly:

1. prettier endOfLine was set to 'crlf' but the repo stores files with
   LF (no .gitattributes forcing eol), so 'prettier --check' failed on
   292 files on the Linux CI runner. Set endOfLine to 'lf' to match the
   on-disk reality. Also reformat the 2 files (pluginBridge.ts,
   solidAdapter.ts) that had genuine style issues.

2. 15 'eslint-disable-next-line' comments targeted oxlint-only rules
   (no-await-in-loop, no-unassigned-vars) that ESLint does not enable,
   so ESLint reported them as 'Unused eslint-disable directive'
   warnings. Switched the directive prefix to 'oxlint-disable-next-line'
   — oxlint still honors them (its native syntax), and ESLint no longer
   parses them as eslint directives, so the warnings are gone without
   suppressing the safety check or removing the directives that oxlint
   actually relies on.

Verified locally: oxlint, tsc --noEmit, eslint, prettier --check, and
npm audit --audit-level=high all exit 0.
This commit is contained in:
Claude
2026-04-07 07:46:49 +00:00
parent 81c121c2bd
commit 6608dd392f
8 changed files with 22 additions and 22 deletions
+1 -1
View File
@@ -57,7 +57,7 @@
"printWidth": 100,
"tabWidth": 2,
"arrowParens": "always",
"endOfLine": "crlf"
"endOfLine": "lf"
},
"dependencies": {
"@jitsi/rnnoise-wasm": "^0.2.1",
@@ -311,7 +311,7 @@ async function clearLogFiles(): Promise<void> {
const entries = await readDir(logDir);
for (const entry of entries) {
if (entry.name?.endsWith(".jsonl") && !entry.isDirectory) {
// eslint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem
// oxlint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem
await remove(`${logDir}/${entry.name}`);
}
}
@@ -14,7 +14,7 @@ export interface PluginContainerProps {
}
export function PluginContainer(props: PluginContainerProps): JSX.Element {
// eslint-disable-next-line no-unassigned-vars -- Solid ref assigned by JSX ref={host}
// oxlint-disable-next-line no-unassigned-vars -- Solid ref assigned by JSX ref={host}
let host!: HTMLDivElement;
let dispose: (() => void) | undefined;
+10 -10
View File
@@ -398,7 +398,7 @@ export class LiveKitSession {
attempt,
maxAttempts: LiveKitSession.MAX_RECONNECT_ATTEMPTS,
});
// eslint-disable-next-line no-await-in-loop -- intentional sequential polling with backoff delay
// oxlint-disable-next-line no-await-in-loop -- intentional sequential polling with backoff delay
await new Promise((r) => setTimeout(r, LiveKitSession.RECONNECT_DELAY_MS));
// If user manually left or joined a different channel during the delay, abort.
if (signal.aborted || this._currentChannelId !== channelId) {
@@ -435,7 +435,7 @@ export class LiveKitSession {
return;
}
// eslint-disable-next-line no-await-in-loop -- sequential reconnect: resolve URL then connect
// oxlint-disable-next-line no-await-in-loop -- sequential reconnect: resolve URL then connect
const resolvedUrl = await this.resolveLiveKitUrl(url, directUrl);
if (signal.aborted || this._currentChannelId !== channelId) {
@@ -449,21 +449,21 @@ export class LiveKitSession {
// If we still have the room key from before disconnect, re-apply it now
// so audio works immediately; the key holder will send a fresh offer if
// the key was rotated during our absence.
// eslint-disable-next-line no-await-in-loop -- must set up E2EE before connect
// oxlint-disable-next-line no-await-in-loop -- must set up E2EE before connect
this._ecdhKeyPair = await generateECDHKeyPair();
this._peerPublicKeys.clear();
if (this._roomKey) {
// eslint-disable-next-line no-await-in-loop -- must set key before connect
// oxlint-disable-next-line no-await-in-loop -- must set key before connect
await this._e2eeKeyProvider.setKey(roomKeyToBase64(this._roomKey));
}
// eslint-disable-next-line no-await-in-loop -- must export before connect
// oxlint-disable-next-line no-await-in-loop -- must export before connect
const reconnectPubKey = await exportPublicKey(this._ecdhKeyPair.publicKey);
this.ws?.send({
type: "voice_e2ee_announce",
payload: { public_key: reconnectPubKey },
});
// eslint-disable-next-line no-await-in-loop -- sequential reconnect: must connect before restoring state
// oxlint-disable-next-line no-await-in-loop -- sequential reconnect: must connect before restoring state
await newRoom.connect(resolvedUrl, token);
if (signal.aborted || this._currentChannelId !== channelId) {
@@ -488,7 +488,7 @@ export class LiveKitSession {
newRoom
.startAudio()
.catch((err) => log.debug("Failed to start audio after reconnect", err));
// eslint-disable-next-line no-await-in-loop -- sequential reconnect: must restore voice state after connect
// oxlint-disable-next-line no-await-in-loop -- sequential reconnect: must restore voice state after connect
await this.restoreLocalVoiceState("reconnect");
// BUG-099: Reapply saved audio devices after reconnect (matches initial join path).
const savedInput = loadPref<string>("audioInputDevice", "");
@@ -907,7 +907,7 @@ export class LiveKitSession {
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
// eslint-disable-next-line no-await-in-loop -- sequential retry: must attempt connect before checking result
// oxlint-disable-next-line no-await-in-loop -- sequential retry: must attempt connect before checking result
await localRoom.connect(resolvedUrl, token);
// Checkpoint 2: after room.connect() — the primary race window.
@@ -959,7 +959,7 @@ export class LiveKitSession {
url: resolvedUrl,
error: connectErr,
});
// eslint-disable-next-line no-await-in-loop -- intentional backoff delay between retry attempts
// oxlint-disable-next-line no-await-in-loop -- intentional backoff delay between retry attempts
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
// Generation check inside retry loop: a superseding join may arrive
// during the backoff delay.
@@ -1133,7 +1133,7 @@ export class LiveKitSession {
) {
this.handleVoiceTokenRefresh(pToken);
} else {
// eslint-disable-next-line no-await-in-loop -- sequential drain of pending joins to avoid unbounded recursion
// oxlint-disable-next-line no-await-in-loop -- sequential drain of pending joins to avoid unbounded recursion
await this.connectAndSetup(pToken, pUrl, pChannelId, pDirectUrl, pIsKeyHolder);
// If this attempt was itself superseded (another join arrived during the
// await), the loop will naturally pick it up via the updated pendingJoin.
@@ -95,7 +95,7 @@ async function rotateOldFiles(): Promise<void> {
if (jsonlFiles.length > MAX_LOG_FILES) {
const toRemove = jsonlFiles.slice(0, jsonlFiles.length - MAX_LOG_FILES);
for (const file of toRemove) {
// eslint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem
// oxlint-disable-next-line no-await-in-loop -- sequential file deletion to avoid overwhelming the filesystem
await remove(`${logDir}/${file}`);
}
}
@@ -187,7 +187,7 @@ export async function readAllPersistedLogs(): Promise<string> {
const parts: string[] = [];
for (const file of jsonlFiles) {
// eslint-disable-next-line no-await-in-loop -- files must be read in sorted order for correct log concatenation
// oxlint-disable-next-line no-await-in-loop -- files must be read in sorted order for correct log concatenation
const content = await readTextFile(`${logDir}/${file}`);
parts.push(content);
}
+5 -1
View File
@@ -109,7 +109,11 @@ class PluginBridge {
this.postToFrame(pluginId, frame, { type, payload });
}
private postToFrame(pluginId: number, frame: HTMLIFrameElement, msg: { type: string; payload: unknown }): void {
private postToFrame(
pluginId: number,
frame: HTMLIFrameElement,
msg: { type: string; payload: unknown },
): void {
// Restrict the postMessage target origin to the host page origin so a
// navigated-away iframe (or one whose contentWindow has been swapped)
// cannot receive host messages intended for a sandboxed plugin. The
+1 -1
View File
@@ -209,7 +209,7 @@ export async function enableScreenshare(
state.manualScreenTracks = screenTracks;
for (const track of screenTracks) {
const isVideo = track.kind === Track.Kind.Video;
// eslint-disable-next-line no-await-in-loop -- tracks must be published sequentially to maintain correct order
// oxlint-disable-next-line no-await-in-loop -- tracks must be published sequentially to maintain correct order
await room.localParticipant.publishTrack(track, {
source: isVideo ? Track.Source.ScreenShare : Track.Source.ScreenShareAudio,
simulcast: false,
+1 -5
View File
@@ -46,11 +46,7 @@ export function fromStoreSlice<T, S>(
): Accessor<S> {
const initial = selector(store.getState());
const [value, setValue] = createSignal<S>(initial, { equals: false });
const unsub = store.subscribeSelector(
selector,
(next) => setValue(() => next),
isEqual,
);
const unsub = store.subscribeSelector(selector, (next) => setValue(() => next), isEqual);
onCleanup(unsub);
return value;
}