fix: resolve all TypeScript build errors blocking Docker CI
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/pop_puller_to_gmail/sessions/47d45081-9f0d-4571-87d9-169ce4ae9fe0
This commit is contained in:
+7
-1
@@ -8,7 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed TypeScript build error in `frontend/src/app/accounts/page.tsx`: replaced non-existent `account.username` with `account.email_address` (the backend intentionally excludes `username` from API responses for security)
|
- Fixed TypeScript build error in `frontend/src/app/accounts/page.tsx`: replaced non-existent `account.username` with `account.email_address`, `account.last_checked_at` with `account.last_check_at`, and `account.last_error` with `account.last_error_message` (the backend intentionally excludes `username` from API responses for security)
|
||||||
|
- Fixed TypeScript error in `frontend/src/app/auth/callback/page.tsx`: `TokenResponse` doesn't include `user`; now fetches user via `userApi.getCurrentUser()` after OAuth token exchange
|
||||||
|
- Fixed TypeScript errors in `frontend/src/app/dashboard/page.tsx`: replaced non-existent `errors_count` with `emails_failed` on `ProcessingRun`
|
||||||
|
- Fixed TypeScript errors in `frontend/src/components/AddMailAccountModal.tsx`: removed invalid `account.username` access, added missing required fields to initial form state, and fixed autoDetect suggestions access
|
||||||
|
- Made `email_address`, `use_tls`, `forward_to` optional in the `MailAccountCreate` TypeScript interface to align with form usage
|
||||||
|
- Added typed suggestion fields to `autoDetect` return type in `api.ts`
|
||||||
|
- Excluded test files (`*.test.ts`, `*.spec.ts`) from TypeScript compilation in `tsconfig.json`
|
||||||
- Upgraded Node.js base image in `frontend/Dockerfile` from `node:18-alpine` to `node:20-alpine` to satisfy the Node.js >= 20.9.0 requirement for Next.js and fix Docker build failures
|
- Upgraded Node.js base image in `frontend/Dockerfile` from `node:18-alpine` to `node:20-alpine` to satisfy the Node.js >= 20.9.0 requirement for Next.js and fix Docker build failures
|
||||||
- Removed `actions/attest-build-provenance` step and associated `id-token: write` / `attestations: write` permissions from the CI `build` job — this action is not available for private user-owned repositories and caused every build to fail
|
- Removed `actions/attest-build-provenance` step and associated `id-token: write` / `attestations: write` permissions from the CI `build` job — this action is not available for private user-owned repositories and caused every build to fail
|
||||||
- Downgraded `eslint` from `^10` to `^9` in the frontend to resolve `TypeError: contextOrFilename.getFilename is not a function` caused by ESLint 10 removing the `getFilename()` API used by `eslint-plugin-react` bundled in `eslint-config-next`
|
- Downgraded `eslint` from `^10` to `^9` in the frontend to resolve `TypeError: contextOrFilename.getFilename is not a function` caused by ESLint 10 removing the `getFilename()` API used by `eslint-plugin-react` bundled in `eslint-config-next`
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { authApi } from '@/lib/api';
|
import { authApi, userApi } from '@/lib/api';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import { Loader2, CheckCircle, XCircle } from 'lucide-react';
|
import { Loader2, CheckCircle, XCircle } from 'lucide-react';
|
||||||
|
|
||||||
@@ -37,8 +37,9 @@ export default function AuthCallbackPage() {
|
|||||||
const response = await authApi.googleAuth(code, redirectUri);
|
const response = await authApi.googleAuth(code, redirectUri);
|
||||||
|
|
||||||
localStorage.setItem('access_token', response.access_token);
|
localStorage.setItem('access_token', response.access_token);
|
||||||
localStorage.setItem('user', JSON.stringify(response.user));
|
const user = response.user ? response.user : await userApi.getCurrentUser();
|
||||||
setUser(response.user);
|
localStorage.setItem('user', JSON.stringify(user));
|
||||||
|
setUser(user);
|
||||||
|
|
||||||
setStatus('success');
|
setStatus('success');
|
||||||
setMessage('Authentication successful! Redirecting...');
|
setMessage('Authentication successful! Redirecting...');
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default function DashboardPage() {
|
|||||||
return new Date(r.started_at).toDateString() === today;
|
return new Date(r.started_at).toDateString() === today;
|
||||||
})
|
})
|
||||||
.reduce((sum, r) => sum + r.emails_forwarded, 0) || 0,
|
.reduce((sum, r) => sum + r.emails_forwarded, 0) || 0,
|
||||||
errors: runs?.filter((r) => r.errors_count > 0).length || 0,
|
errors: runs?.filter((r) => r.emails_failed > 0).length || 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -166,8 +166,8 @@ export default function DashboardPage() {
|
|||||||
{run.emails_forwarded}
|
{run.emails_forwarded}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
{run.errors_count > 0 ? (
|
{run.emails_failed > 0 ? (
|
||||||
<span className="text-red-600 font-medium">{run.errors_count}</span>
|
<span className="text-red-600 font-medium">{run.emails_failed}</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-gray-400">0</span>
|
<span className="text-gray-400">0</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro
|
|||||||
protocol: account?.protocol || 'pop3',
|
protocol: account?.protocol || 'pop3',
|
||||||
host: account?.host || '',
|
host: account?.host || '',
|
||||||
port: account?.port || 995,
|
port: account?.port || 995,
|
||||||
username: account?.username || '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
use_ssl: account?.use_ssl ?? true,
|
use_ssl: account?.use_ssl ?? true,
|
||||||
check_interval_minutes: account?.check_interval_minutes || 5,
|
check_interval_minutes: account?.check_interval_minutes || 5,
|
||||||
@@ -70,14 +70,17 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro
|
|||||||
|
|
||||||
setAutoDetecting(true);
|
setAutoDetecting(true);
|
||||||
try {
|
try {
|
||||||
const settings = await mailAccountsApi.autoDetect(formData.username);
|
const result = await mailAccountsApi.autoDetect(formData.username);
|
||||||
setFormData((prev) => ({
|
const suggestion = result.success && result.suggestions.length > 0 ? result.suggestions[0] : null;
|
||||||
...prev,
|
if (suggestion) {
|
||||||
protocol: settings.protocol || prev.protocol,
|
setFormData((prev) => ({
|
||||||
host: settings.host || prev.host,
|
...prev,
|
||||||
port: settings.port || prev.port,
|
protocol: suggestion.protocol || prev.protocol,
|
||||||
use_ssl: settings.use_ssl ?? prev.use_ssl,
|
host: suggestion.host || prev.host,
|
||||||
}));
|
port: suggestion.port || prev.port,
|
||||||
|
use_ssl: suggestion.use_ssl ?? prev.use_ssl,
|
||||||
|
}));
|
||||||
|
}
|
||||||
alert('Settings auto-detected successfully!');
|
alert('Settings auto-detected successfully!');
|
||||||
} catch {
|
} catch {
|
||||||
alert('Failed to auto-detect settings. Please enter manually.');
|
alert('Failed to auto-detect settings. Please enter manually.');
|
||||||
|
|||||||
+14
-5
@@ -82,15 +82,15 @@ export interface MailAccount {
|
|||||||
|
|
||||||
export interface MailAccountCreate {
|
export interface MailAccountCreate {
|
||||||
name: string;
|
name: string;
|
||||||
email_address: string;
|
email_address?: string;
|
||||||
protocol: string;
|
protocol: string;
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
use_ssl: boolean;
|
use_ssl: boolean;
|
||||||
use_tls: boolean;
|
use_tls?: boolean;
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
forward_to: string;
|
forward_to?: string;
|
||||||
delivery_method?: string;
|
delivery_method?: string;
|
||||||
is_enabled?: boolean;
|
is_enabled?: boolean;
|
||||||
check_interval_minutes?: number;
|
check_interval_minutes?: number;
|
||||||
@@ -111,10 +111,19 @@ export interface ProcessingRun {
|
|||||||
error_message?: string | null;
|
error_message?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AutoDetectSuggestion {
|
||||||
|
protocol?: string;
|
||||||
|
host?: string;
|
||||||
|
port?: number;
|
||||||
|
use_ssl?: boolean;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
interface TokenResponse {
|
interface TokenResponse {
|
||||||
access_token: string;
|
access_token: string;
|
||||||
refresh_token: string;
|
refresh_token: string;
|
||||||
token_type: string;
|
token_type: string;
|
||||||
|
user?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Auth API ────────────────────────────────────────────────────────────
|
// ── Auth API ────────────────────────────────────────────────────────────
|
||||||
@@ -215,10 +224,10 @@ export const mailAccountsApi = {
|
|||||||
|
|
||||||
async autoDetect(
|
async autoDetect(
|
||||||
emailAddress: string
|
emailAddress: string
|
||||||
): Promise<{ success: boolean; suggestions: Record<string, unknown>[] }> {
|
): Promise<{ success: boolean; suggestions: AutoDetectSuggestion[] }> {
|
||||||
const response = await api.post<{
|
const response = await api.post<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
suggestions: Record<string, unknown>[];
|
suggestions: AutoDetectSuggestion[];
|
||||||
}>("/mail-accounts/auto-detect", { email_address: emailAddress });
|
}>("/mail-accounts/auto-detect", { email_address: emailAddress });
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,5 +30,5 @@
|
|||||||
".next/dev/types/**/*.ts",
|
".next/dev/types/**/*.ts",
|
||||||
"**/*.mts"
|
"**/*.mts"
|
||||||
],
|
],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user