diff --git a/package.json b/package.json
index f18ba1cec92..612e9a79a43 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"@lichess-org/chessground": "^10.1.0",
"@lichess-org/pgn-viewer": "^2.6",
"@types/lichess": "workspace:*",
- "@types/node": "^24.12.0",
+ "@types/node": "^24.12.2",
"ab": "github:lichess-org/ab-stub",
"chessops": "^0.15",
"jsdom": "^27.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6d85e5613c2..f65fc535484 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,8 +23,8 @@ importers:
specifier: workspace:*
version: link:ui/@types/lichess
'@types/node':
- specifier: ^24.12.0
- version: 24.12.0
+ specifier: ^24.12.2
+ version: 24.12.2
ab:
specifier: github:lichess-org/ab-stub
version: https://codeload.github.com/lichess-org/ab-stub/tar.gz/94236bf34dbc9c05daf50f4c9842d859b9142be0
@@ -1110,8 +1110,8 @@ packages:
'@types/node@24.10.13':
resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==}
- '@types/node@24.12.0':
- resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==}
+ '@types/node@24.12.2':
+ resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==}
'@types/qrcode@1.5.6':
resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==}
@@ -2704,13 +2704,13 @@ snapshots:
dependencies:
undici-types: 7.16.0
- '@types/node@24.12.0':
+ '@types/node@24.12.2':
dependencies:
undici-types: 7.16.0
'@types/qrcode@1.5.6':
dependencies:
- '@types/node': 24.12.0
+ '@types/node': 24.12.2
'@types/react@19.1.9':
dependencies:
diff --git a/ui/bits/src/bits.auth.ts b/ui/bits/src/bits.auth.ts
index 5829f93f2e9..6b610da7948 100644
--- a/ui/bits/src/bits.auth.ts
+++ b/ui/bits/src/bits.auth.ts
@@ -88,8 +88,8 @@ function signupStart() {
else return false;
});
- $form.find('.password-generator button').on('click', () => {
- site.asset.loadEsm('bits.passwordGenerator', { init: 'form3-password' });
+ $form.find('.password-generator button').on('click', async () => {
+ await site.asset.loadEsm('bits.passwordGenerator', { init: 'form3-password' });
return false;
});
const showPasswordTools = () => {
@@ -99,7 +99,7 @@ function signupStart() {
$password.on('input', showPasswordTools);
showPasswordTools();
- site.asset.loadEsm('bits.passwordComplexity', { init: 'form3-password' });
+ void site.asset.loadEsm('bits.passwordComplexity', { init: 'form3-password' });
}
function initTextClear(form: HTMLFormElement) {
@@ -119,5 +119,5 @@ function initTextClear(form: HTMLFormElement) {
}
function resetStart() {
- site.asset.loadEsm('bits.passwordComplexity', { init: 'form3-newPasswd1' });
+ void site.asset.loadEsm('bits.passwordComplexity', { init: 'form3-newPasswd1' });
}
diff --git a/ui/bits/src/bits.challengePage.ts b/ui/bits/src/bits.challengePage.ts
index 2d15fb10238..24736a0f474 100644
--- a/ui/bits/src/bits.challengePage.ts
+++ b/ui/bits/src/bits.challengePage.ts
@@ -39,9 +39,9 @@ export function initModule(opts: ChallengeOpts): void {
});
$(selector)
.find('form.xhr')
- .on('submit', function (this: HTMLFormElement, e) {
+ .on('submit', async function (this: HTMLFormElement, e) {
e.preventDefault();
- xhr.formToXhr(this);
+ await xhr.formToXhr(this);
$(this).html('');
});
$(selector)
diff --git a/ui/bits/src/bits.cms.ts b/ui/bits/src/bits.cms.ts
index 5ae00175836..032dbdf9c10 100644
--- a/ui/bits/src/bits.cms.ts
+++ b/ui/bits/src/bits.cms.ts
@@ -5,10 +5,11 @@ import { makeToastEditor, getSanitizedMarkdown } from './toastEditor';
site.load.then(() => {
$('.markdown-toastui').each(function (this: HTMLTextAreaElement) {
- const editor = makeToastEditor(this, $('#form3-markdown').val() as string, '60vh');
+ const markdownForm = $('#form3-markdown');
+ const editor = makeToastEditor(this, markdownForm.val() as string, '60vh');
editor.on(
'change',
- throttle(500, () => $('#form3-markdown').val(getSanitizedMarkdown(editor))),
+ throttle(500, () => markdownForm.val(getSanitizedMarkdown(editor))),
);
});
$('.flash').addClass('fade');
diff --git a/ui/bits/src/bits.diagnosticDialog.ts b/ui/bits/src/bits.diagnosticDialog.ts
index 655bdf802df..2c5b9843d09 100644
--- a/ui/bits/src/bits.diagnosticDialog.ts
+++ b/ui/bits/src/bits.diagnosticDialog.ts
@@ -71,7 +71,7 @@ export async function initModule(opts?: DiagnosticOpts): Promise {
setTimeout(() => copied.remove(), 2000);
}),
);
- dlg.show();
+ await dlg.show();
}
const storageProxy: Record boolean }> = {
diff --git a/ui/bits/src/bits.flairPicker.ts b/ui/bits/src/bits.flairPicker.ts
index 8ceb146709e..71beaac6f7d 100644
--- a/ui/bits/src/bits.flairPicker.ts
+++ b/ui/bits/src/bits.flairPicker.ts
@@ -37,7 +37,7 @@ const makeEmojiData = async () => {
const res = await fetch(site.asset.url('flair/list.txt', { pathVersion: true }));
const text = await res.text();
const lines = text.split('\n').slice(0, -1);
- const data = {
+ return {
categories: categories.map(([id, name]) => ({
id: id,
name: name,
@@ -62,7 +62,6 @@ const makeEmojiData = async () => {
}),
),
};
- return data;
};
const categories: [string, string][] = [
diff --git a/ui/bits/src/bits.forum.ts b/ui/bits/src/bits.forum.ts
index 79a8e50958c..4655924c7e3 100644
--- a/ui/bits/src/bits.forum.ts
+++ b/ui/bits/src/bits.forum.ts
@@ -19,9 +19,9 @@ site.load.then(() => {
$(dlg.view)
.find('form')
.attr('action', link.href)
- .on('submit', function (this: HTMLFormElement, e: Event) {
+ .on('submit', async function (this: HTMLFormElement, e: Event) {
e.preventDefault();
- xhr.formToXhr(this);
+ await xhr.formToXhr(this);
$(link).closest('.forum-post').hide();
dlg.close();
});
@@ -43,9 +43,9 @@ site.load.then(() => {
});
return false;
})
- .on('click', 'form.unsub button', function (this: HTMLButtonElement) {
+ .on('click', 'form.unsub button', async function (this: HTMLButtonElement) {
const form = $(this).parent().toggleClass('on off')[0] as HTMLFormElement;
- xhr.text(`${form.action}?unsub=${this.dataset.unsub}`, { method: 'post' });
+ await xhr.text(`${form.action}?unsub=${this.dataset.unsub}`, { method: 'post' });
return false;
})
.on('click', '.reactions-auth button', e => {
diff --git a/ui/bits/src/bits.markdownTextarea.ts b/ui/bits/src/bits.markdownTextarea.ts
index 6dc6b2ff494..58965feb09c 100644
--- a/ui/bits/src/bits.markdownTextarea.ts
+++ b/ui/bits/src/bits.markdownTextarea.ts
@@ -31,10 +31,10 @@ function wireMarkdownTextarea(markdown: HTMLElement) {
writeTab.classList.remove('active');
previewTab.classList.add('active');
if (markdownPicfitRegex().test(textarea.value) && !localStorage.getItem('markdown.rtfm')) {
- info('Drag a side or bottom edge to resize an image.');
+ await info('Drag a side or bottom edge to resize an image.');
localStorage.setItem('markdown.rtfm', '1');
}
- wireMarkdownImgResizers({
+ await wireMarkdownImgResizers({
root: preview,
update: {
markdown: (text?: string) => (text !== undefined ? (textarea.value = text) : textarea.value),
diff --git a/ui/bits/src/bits.streamerEdit.ts b/ui/bits/src/bits.streamerEdit.ts
index a2e9d228e55..59cb84c5f66 100644
--- a/ui/bits/src/bits.streamerEdit.ts
+++ b/ui/bits/src/bits.streamerEdit.ts
@@ -8,7 +8,7 @@ type MaybeEl = HTMLElement | null;
type OAuthBox = { div: HTMLElement; linkBtn: MaybeEl; unlinkBtn: MaybeEl; url: HTMLAnchorElement | null };
type OAuthBoxes = Record;
-export function initModule(): any {
+export function initModule(): void {
const el = scopedQuery(document.querySelector('.streamer-edit')!);
const platforms: Platform[] = ['twitch', 'youtube'];
const oauths = platforms.reduce((acc, platform) => {
diff --git a/ui/bits/src/bits.team.ts b/ui/bits/src/bits.team.ts
index 9380abfaa31..bee832a43a2 100644
--- a/ui/bits/src/bits.team.ts
+++ b/ui/bits/src/bits.team.ts
@@ -19,8 +19,8 @@ export function initModule(opts: TeamOpts): void {
$('#team-subscribe').on('change', function (this: HTMLInputElement) {
$(this)
.parents('form')
- .each(function (this: HTMLFormElement) {
- xhr.formToXhr(this);
+ .each(async function (this: HTMLFormElement) {
+ await xhr.formToXhr(this);
});
});
}
@@ -35,6 +35,6 @@ $('button.explain').on('click', async e => {
}
});
-$('.emoji-details').each(function (this: HTMLElement) {
- flairPickerLoader(this);
+$('.emoji-details').each(async function (this: HTMLElement) {
+ await flairPickerLoader(this);
});
diff --git a/ui/bits/src/bits.ublog.ts b/ui/bits/src/bits.ublog.ts
index 8c546983c7c..5fe5d48dd9a 100644
--- a/ui/bits/src/bits.ublog.ts
+++ b/ui/bits/src/bits.ublog.ts
@@ -123,12 +123,12 @@ function rewireModPost() {
submitBtn.disabled = false;
}),
);
- submitBtn.addEventListener('click', () => {
+ submitBtn.addEventListener('click', async () => {
const form: Record = {};
for (const input of submitFields.querySelectorAll('input')) {
form[input.id] = input.type === 'checkbox' ? input.checked : input.value;
}
- submit(form);
+ await submit(form);
});
modTools
.querySelector('.carousel-add-btn')
@@ -138,7 +138,7 @@ function rewireModPost() {
?.addEventListener('click', () => submit({ featured: false }));
modTools.querySelector('.carousel-pin-btn')?.addEventListener('click', async () => {
const days = await prompt('How many days?', '7', (n: string) => Number(n) > 0 && Number(n) < 31);
- if (days) submit({ featured: true, featuredUntil: Number(days) });
+ if (days) await submit({ featured: true, featuredUntil: Number(days) });
});
assessBtn.addEventListener('click', async () => {
assessBtn.insertAdjacentHTML('afterend', spinnerHtml);
diff --git a/ui/bits/src/bits.ublogForm.ts b/ui/bits/src/bits.ublogForm.ts
index 70b7eec0c54..3f1aee67cb0 100644
--- a/ui/bits/src/bits.ublogForm.ts
+++ b/ui/bits/src/bits.ublogForm.ts
@@ -7,10 +7,11 @@ import { makeToastEditor, getSanitizedMarkdown } from './toastEditor';
site.load.then(() => {
$('.markdown-toastui').each(function (this: HTMLTextAreaElement) {
- const editor = makeToastEditor(this, $('#form3-markdown').val() as string, '60vh');
+ const markdownForm = $('#form3-markdown');
+ const editor = makeToastEditor(this, markdownForm.val() as string, '60vh');
editor.on(
'change',
- throttle(500, () => $('#form3-markdown').val(getSanitizedMarkdown(editor))),
+ throttle(500, () => markdownForm.val(getSanitizedMarkdown(editor))),
);
});
$('#form3-topics').each(function (this: HTMLTextAreaElement) {
diff --git a/ui/site/src/serviceWorker.ts b/ui/site/src/serviceWorker.ts
index 27e9e88f91a..66556ffb57b 100644
--- a/ui/site/src/serviceWorker.ts
+++ b/ui/site/src/serviceWorker.ts
@@ -33,6 +33,6 @@ export default async function () {
else throw new Error(res.statusText);
} catch (err: any) {
log('serviceWorker.ts:', err.message, newSub);
- if (newSub?.endpoint) newSub.unsubscribe();
+ if (newSub && newSub?.endpoint) await newSub.unsubscribe();
}
}
diff --git a/ui/site/src/unhandledError.ts b/ui/site/src/unhandledError.ts
index 6a9d050d39c..0b7d8d816aa 100644
--- a/ui/site/src/unhandledError.ts
+++ b/ui/site/src/unhandledError.ts
@@ -9,9 +9,9 @@ function terseHref(): string {
export function addExceptionListeners() {
window.addEventListener('error', async e => {
const loc = e.filename ? ` - (${e.filename}:${e.lineno}:${e.colno})` : '';
- log(`${terseHref()} - ${e.message}${loc}\n${e.error?.stack ?? ''}`.trim());
+ await log(`${terseHref()} - ${e.message}${loc}\n${e.error?.stack ?? ''}`.trim());
if (site.debug)
- domDialog({
+ await domDialog({
htmlText: escapeHtml(`${e.message}${loc}\n${e.error?.stack ?? ''}`),
class: 'debug',
show: true,
@@ -26,9 +26,9 @@ export function addExceptionListeners() {
} catch (_) {
reason = 'unhandled rejection, reason not a string';
}
- log(`${terseHref()} - ${reason}`);
+ await log(`${terseHref()} - ${reason}`);
if (site.debug)
- domDialog({
+ await domDialog({
htmlText: escapeHtml(reason),
class: 'debug',
show: true,