inline email resync instead of job queue, refresh list on completion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 17:07:06 +00:00
co-authored by Claude Opus 4.6
parent ea8113e61d
commit b3f1d10bc1
7 changed files with 367 additions and 83 deletions
+5 -5
View File
@@ -17,7 +17,7 @@ import { refreshGoogleAccessToken } from '@@/api/integrations/google-auth';
// ── Credentials ──
type GmailCredentials = {
export type GmailCredentials = {
email: string;
userId: number;
appPassword?: string;
@@ -26,7 +26,7 @@ type GmailCredentials = {
expiresAt?: number;
};
async function loadGmailCredentials(userEmail: string): Promise<GmailCredentials> {
export async function loadGmailCredentials(userEmail: string): Promise<GmailCredentials> {
const dbUser = await getUserByEmail(userEmail);
if (!dbUser) throw new PermanentError('User not found');
@@ -102,7 +102,7 @@ function shouldSkipMessage(labelIds: string[]): boolean {
const GMAIL_API = 'https://gmail.googleapis.com/gmail/v1/users/me';
type GmailApiResult = { saved: number; skipped: number; errors: number };
export type GmailApiResult = { saved: number; skipped: number; errors: number };
async function gmailApiFetch(accessToken: string, path: string, params?: Record<string, string>): Promise<Response> {
const url = new URL(`${GMAIL_API}${path}`);
@@ -219,13 +219,13 @@ async function fetchRawMessage(accessToken: string, messageId: string): Promise<
// ── Gmail API sync (for resyncs) ──
type GmailApiSyncParams = {
export type GmailApiSyncParams = {
creds: GmailCredentials;
db: Database;
onProgress?: (saved: number, total: number) => void;
};
async function gmailApiSync({ creds, db, onProgress }: GmailApiSyncParams): Promise<GmailApiResult> {
export async function gmailApiSync({ creds, db, onProgress }: GmailApiSyncParams): Promise<GmailApiResult> {
if (!creds.accessToken) throw new PermanentError('OAuth access token required for Gmail API sync');
let saved = 0;