Adding: themes, predictions, match reporting, ui fixes, sse fixes, badge fixes, match flow, i18n, match edits, perf, auth fix #22

Merged
kyle merged 43 commits from development into main 2026-08-23 23:09:01 -05:00
Showing only changes of commit 60e91d1371 - Show all commits
+35 -3
View File
@@ -19,17 +19,38 @@ class PocketBaseAdminClient {
this.pb = new PocketBase(process.env.POCKETBASE_URL);
this.pb.beforeSend = async (url, options) => {
// The auth requests themselves must skip the gate below: gating them on
// authPromise would make them await their own completion (deadlock).
if (!url.includes("/collections/_superusers/auth-")) {
try {
await this.authPromise;
} catch {
// Swallow: fall through to self-heal so a rejected authPromise can't strand every request.
}
if (this.pb.authStore.isValid && this.isTokenExpiringSoon()) {
if (!this.pb.authStore.isValid) {
// Self-heal: re-auth once PocketBase is reachable again, no restart.
this.authPromise = this.authenticate();
await this.authPromise;
this.startTokenRefresh();
} else if (this.isTokenExpiringSoon()) {
try {
await this.refreshAuth();
} catch (error) {
console.error('Failed to refresh admin token, re-authenticating:', error);
await this.authenticate();
this.authPromise = this.authenticate();
await this.authPromise;
}
}
// The SDK stamps Authorization before this hook runs, so a request
// built while auth was still in flight carries no (or a stale) token.
options.headers = {
...options.headers,
Authorization: this.pb.authStore.token,
};
}
options.cache = "no-store";
options.headers = {
...options.headers,
@@ -54,8 +75,17 @@ class PocketBaseAdminClient {
Object.assign(this, createPushService(this.pb));
this.authPromise = this.authenticate();
this.authPromise.then(() => {
// Fail soft at boot: an unreachable PocketBase must not crash the process;
// beforeSend self-heals on the next request.
this.authPromise
.then(() => {
this.startTokenRefresh();
})
.catch(() => {
console.error(
"PocketBase admin authentication failed - is PocketBase running and are " +
"POCKETBASE_URL / POCKETBASE_ADMIN_EMAIL / POCKETBASE_ADMIN_PASSWORD set?"
);
});
}
@@ -98,6 +128,8 @@ class PocketBaseAdminClient {
}
private startTokenRefresh() {
if (this.refreshInterval) return;
this.refreshInterval = setInterval(async () => {
try {
await this.refreshAuth();