mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-07-16 04:23:43 +00:00
feat(#89): Add backup functionality for google drive and dropbox
This commit is contained in:
@@ -14,6 +14,7 @@ type QueueItem = {
|
||||
attempts: number;
|
||||
notBefore: number; // unix ms
|
||||
debounceTimer: ReturnType<typeof setTimeout> | null;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export type CreateCatchRecordWriteQueueOptions = {
|
||||
@@ -157,14 +158,25 @@ export function createCatchRecordWriteQueue(options: CreateCatchRecordWriteQueue
|
||||
}
|
||||
|
||||
// Success: drop the flushed keys.
|
||||
for (const [k] of eligible) {
|
||||
items.delete(k);
|
||||
for (const [k, sentItem] of eligible) {
|
||||
const current = items.get(k);
|
||||
if (!current) {
|
||||
items.delete(k);
|
||||
continue;
|
||||
}
|
||||
// Only clear if nothing newer was enqueued after this batch started.
|
||||
if (current.version === sentItem.version) {
|
||||
items.delete(k);
|
||||
}
|
||||
}
|
||||
updateStatus({ lastError: null, lastSuccessfulFlushAt: Date.now() });
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : String(e);
|
||||
// Backoff all eligible items and keep them.
|
||||
for (const [k, item] of eligible) {
|
||||
const current = items.get(k);
|
||||
if (!current) continue;
|
||||
if (current.version !== item.version) continue;
|
||||
const nextAttempts = item.attempts + 1;
|
||||
items.set(k, {
|
||||
...item,
|
||||
@@ -199,6 +211,7 @@ export function createCatchRecordWriteQueue(options: CreateCatchRecordWriteQueue
|
||||
const now = Date.now();
|
||||
const existing = items.get(k);
|
||||
const debounceMs = opts?.debounceMs ?? 0;
|
||||
const nextVersion = (existing?.version ?? 0) + 1;
|
||||
|
||||
// Clear any pending debounce timer: latest state always wins.
|
||||
if (existing?.debounceTimer) {
|
||||
@@ -222,7 +235,8 @@ export function createCatchRecordWriteQueue(options: CreateCatchRecordWriteQueue
|
||||
record,
|
||||
attempts: existing?.attempts ?? 0,
|
||||
notBefore,
|
||||
debounceTimer
|
||||
debounceTimer,
|
||||
version: nextVersion
|
||||
});
|
||||
updateStatus({});
|
||||
if (opts?.flushSoon !== false) scheduleFlush();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
export function getEnv() {
|
||||
return process.env;
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import type { RequestEvent } from '@sveltejs/kit';
|
||||
|
||||
export type OAuthStatePayload = {
|
||||
state: string;
|
||||
userId: string;
|
||||
pokedexId?: string | null;
|
||||
provider: string;
|
||||
fileName?: string | null;
|
||||
folderId?: string | null;
|
||||
path?: string | null;
|
||||
returnTo?: string | null;
|
||||
};
|
||||
|
||||
const STATE_MAX_AGE = 10 * 60; // 10 minutes
|
||||
|
||||
export function createOAuthState(): string {
|
||||
return randomUUID();
|
||||
}
|
||||
|
||||
function cookieName(provider: string): string {
|
||||
return `oauth_state_${provider}`;
|
||||
}
|
||||
|
||||
export function setOAuthStateCookie(
|
||||
event: RequestEvent,
|
||||
provider: string,
|
||||
payload: OAuthStatePayload
|
||||
) {
|
||||
event.cookies.set(cookieName(provider), JSON.stringify(payload), {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: event.url.protocol === 'https:',
|
||||
maxAge: STATE_MAX_AGE
|
||||
});
|
||||
}
|
||||
|
||||
export function readOAuthStateCookie(
|
||||
event: RequestEvent,
|
||||
provider: string
|
||||
): OAuthStatePayload | null {
|
||||
const raw = event.cookies.get(cookieName(provider));
|
||||
if (!raw) return null;
|
||||
try {
|
||||
const parsed = JSON.parse(raw) as OAuthStatePayload;
|
||||
if (!parsed?.state || !parsed?.userId) return null;
|
||||
return parsed;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function clearOAuthStateCookie(event: RequestEvent, provider: string) {
|
||||
event.cookies.delete(cookieName(provider), { path: '/' });
|
||||
}
|
||||
Reference in New Issue
Block a user