Fix pre-commit script to properly handle multiple files and resolve ESLint warnings

This commit is contained in:
William Valentin
2025-09-07 13:34:39 -07:00
parent 8fa2d3fb60
commit 315303b120
33 changed files with 561 additions and 404 deletions
@@ -1,6 +1,5 @@
import { authService } from '../auth.service';
import { AccountStatus } from '../auth.constants';
import { User } from '../../../types';
// Helper to clear localStorage and reset the mock DB before each test
beforeEach(() => {
@@ -1,5 +1,4 @@
import { EmailVerificationService } from '../emailVerification.service';
import { dbService } from '../../couchdb.factory';
jest.mock('../../couchdb.factory');
jest.mock('../../email');
+1 -1
View File
@@ -31,7 +31,7 @@ export const authenticate = (
};
// Security: Role-based authorization middleware
export const authorize = (...allowedRoles: string[]) => {
export const authorize = (..._allowedRoles: string[]) => {
return (req: Request, res: Response, next: NextFunction) => {
try {
// Security: Check if user exists in request
+15 -11
View File
@@ -1,7 +1,5 @@
import { v4 as uuidv4 } from 'uuid';
import { dbService } from '../../services/couchdb.factory';
import { AccountStatus } from './auth.constants';
import { User } from '../../types';
import { AuthenticatedUser } from './auth.types';
import { EmailVerificationService } from './emailVerification.service';
@@ -33,17 +31,17 @@ const authService = {
},
async login(input: { email: string; password: string }) {
console.log('🔐 Login attempt for:', input.email);
console.warn('🔐 Login attempt for:', input.email);
// Find user by email
const user = await dbService.findUserByEmail(input.email);
if (!user) {
console.log('❌ User not found for email:', input.email);
console.warn('❌ User not found for email:', input.email);
throw new Error('User not found');
}
console.log('👤 User found:', {
console.warn('👤 User found:', {
email: user.email,
hasPassword: !!user.password,
role: user.role,
@@ -53,25 +51,25 @@ const authService = {
// Check if user has a password (email-based account)
if (!user.password) {
console.log('❌ No password found - OAuth account');
console.warn('❌ No password found - OAuth account');
throw new Error(
'This account was created with OAuth. Please use Google or GitHub to sign in.'
);
}
// Simple password verification (in production, use bcrypt)
console.log('🔍 Comparing passwords:', {
console.warn('🔍 Comparing passwords:', {
inputPassword: input.password,
storedPassword: user.password,
match: user.password === input.password,
});
if (user.password !== input.password) {
console.log('❌ Password mismatch');
console.warn('❌ Password mismatch');
throw new Error('Invalid password');
}
console.log('✅ Login successful for:', user.email);
console.warn('✅ Login successful for:', user.email);
// Return mock tokens for frontend compatibility
return {
@@ -204,7 +202,10 @@ const authService = {
const resetTokens = JSON.parse(
localStorage.getItem('password_reset_tokens') || '[]'
);
const resetToken = resetTokens.find((t: any) => t.token === token);
const resetToken = resetTokens.find(
(t: { token: string; userId: string; email: string; expiresAt: Date }) =>
t.token === token
);
if (!resetToken) {
throw new Error('Invalid or expired reset token');
@@ -227,7 +228,10 @@ const authService = {
);
// Remove used token
const filteredTokens = resetTokens.filter((t: any) => t.token !== token);
const filteredTokens = resetTokens.filter(
(t: { token: string; userId: string; email: string; expiresAt: Date }) =>
t.token !== token
);
localStorage.setItem(
'password_reset_tokens',
JSON.stringify(filteredTokens)
+2 -2
View File
@@ -6,7 +6,7 @@ import { CouchDBService as MockCouchDBService } from './couchdb';
// Environment detection
const isProduction = () => {
// Check if we're in a Docker environment or if CouchDB URL is configured
const env = (import.meta as any).env || {};
const env = (import.meta as { env?: Record<string, string> }).env || {};
const couchdbUrl =
env.VITE_COUCHDB_URL ||
(typeof process !== 'undefined' ? process.env.VITE_COUCHDB_URL : null) ||
@@ -20,7 +20,7 @@ const createDbService = () => {
if (isProduction()) {
try {
// Use dynamic require to avoid TypeScript resolution issues
// eslint-disable-next-line @typescript-eslint/no-var-requires
const {
CouchDBService: RealCouchDBService,
} = require('./couchdb.production');
+19 -15
View File
@@ -18,11 +18,9 @@ export class CouchDBService {
constructor() {
// Get CouchDB configuration from environment
const couchdbUrl =
(import.meta as any).env?.VITE_COUCHDB_URL || 'http://localhost:5984';
const couchdbUser = (import.meta as any).env?.VITE_COUCHDB_USER || 'admin';
const couchdbPassword =
(import.meta as any).env?.VITE_COUCHDB_PASSWORD || 'password';
const couchdbUrl = process.env.VITE_COUCHDB_URL || 'http://localhost:5984';
const couchdbUser = process.env.VITE_COUCHDB_USER || 'admin';
const couchdbPassword = process.env.VITE_COUCHDB_PASSWORD || 'password';
this.baseUrl = couchdbUrl;
this.auth = btoa(`${couchdbUser}:${couchdbPassword}`);
@@ -72,7 +70,7 @@ export class CouchDBService {
throw new Error(`Failed to create database ${dbName}`);
}
console.log(`✅ Created CouchDB database: ${dbName}`);
console.warn(`✅ Created CouchDB database: ${dbName}`);
}
} catch (error) {
console.error(`Error checking/creating database ${dbName}:`, error);
@@ -83,8 +81,8 @@ export class CouchDBService {
private async makeRequest(
method: string,
path: string,
body?: any
): Promise<any> {
body?: Record<string, unknown>
): Promise<Record<string, unknown>> {
const url = `${this.baseUrl}${path}`;
const options: RequestInit = {
method,
@@ -114,7 +112,7 @@ export class CouchDBService {
): Promise<T | null> {
try {
const doc = await this.makeRequest('GET', `/${dbName}/${id}`);
return doc;
return doc as T;
} catch (error) {
if (error instanceof CouchDBError && error.status === 404) {
return null;
@@ -135,12 +133,15 @@ export class CouchDBService {
return { ...doc, _rev: response.rev } as T;
}
private async query<T>(dbName: string, selector: any): Promise<T[]> {
private async query<T>(
dbName: string,
selector: Record<string, unknown>
): Promise<T[]> {
const response = await this.makeRequest('POST', `/${dbName}/_find`, {
selector,
limit: 1000,
});
return response.docs;
return response.docs as T[];
}
// User Management Methods
@@ -363,10 +364,13 @@ export class CouchDBService {
const settings = await this.getDoc('settings', userId);
if (settings) {
deletePromises.push(
this.makeRequest('DELETE', `/settings/${userId}?rev=${settings._rev}`)
this.makeRequest(
'DELETE',
`/settings/${userId}?rev=${settings._rev}`
).then(() => undefined)
);
}
} catch (error) {
} catch (_error) {
// Settings might not exist
}
@@ -377,10 +381,10 @@ export class CouchDBService {
this.makeRequest(
'DELETE',
`/taken_doses/${userId}?rev=${takenDoses._rev}`
)
).then(() => undefined)
);
}
} catch (error) {
} catch (_error) {
// Taken doses might not exist
}
+13 -13
View File
@@ -23,14 +23,14 @@ export class MailgunService {
// Log configuration status on startup
const status = this.getConfigurationStatus();
if (status.mode === 'development') {
console.log(
console.warn(
'📧 Mailgun Service: Running in development mode (emails will be logged only)'
);
console.log(
console.warn(
'💡 To enable real emails, configure Mailgun credentials in .env.local'
);
} else {
console.log(
console.warn(
'📧 Mailgun Service: Configured for production with domain:',
status.domain
);
@@ -45,8 +45,8 @@ export class MailgunService {
<h2 style="color: #4f46e5;">Verify Your Email Address</h2>
<p>Thank you for signing up for Medication Reminder! Please click the button below to verify your email address:</p>
<div style="text-align: center; margin: 30px 0;">
<a href="${verificationUrl}"
style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
<a href="${verificationUrl}"
style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
Verify Email Address
</a>
</div>
@@ -57,10 +57,10 @@ export class MailgunService {
`,
text: `
Verify Your Email - Medication Reminder
Thank you for signing up! Please verify your email by visiting:
${verificationUrl}
This link will expire in 24 hours.
`,
};
@@ -74,8 +74,8 @@ export class MailgunService {
<h2 style="color: #4f46e5;">Reset Your Password</h2>
<p>You requested to reset your password. Click the button below to set a new password:</p>
<div style="text-align: center; margin: 30px 0;">
<a href="${resetUrl}"
style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
<a href="${resetUrl}"
style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block;">
Reset Password
</a>
</div>
@@ -86,10 +86,10 @@ export class MailgunService {
`,
text: `
Reset Your Password - Medication Reminder
You requested to reset your password. Visit this link to set a new password:
${resetUrl}
This link will expire in 1 hour. If you didn't request this, please ignore this email.
`,
};
@@ -99,7 +99,7 @@ export class MailgunService {
try {
// In development mode or when Mailgun is not configured, just log the email
if (isDevelopmentMode()) {
console.log('📧 Mock Email Sent (Development Mode):', {
console.warn('📧 Mock Email Sent (Development Mode):', {
to,
subject: template.subject,
from: `${this.config.fromName} <${this.config.fromEmail}>`,
@@ -140,7 +140,7 @@ export class MailgunService {
}
const result = await response.json();
console.log('📧 Email sent successfully via Mailgun:', {
console.warn('📧 Email sent successfully via Mailgun:', {
to,
subject: template.subject,
messageId: result.id,
+2 -7
View File
@@ -1,7 +1,4 @@
import { authService } from './auth/auth.service';
import { OAuthProvider, OAuthState, User } from '../types';
import { dbService } from './couchdb.factory';
import { AccountStatus } from './auth/auth.constants';
// Mock OAuth configuration
const GOOGLE_CLIENT_ID = 'mock_google_client_id';
@@ -12,8 +9,6 @@ const GOOGLE_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';
const GITHUB_AUTH_URL = 'https://github.com/login/oauth/authorize';
// Mock token exchange endpoints
const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token';
const GITHUB_TOKEN_URL = 'https://github.com/login/oauth/access_token';
// Mock OAuth scopes
const GOOGLE_SCOPES = 'openid email profile';
@@ -60,7 +55,7 @@ export const githubAuth = () => {
// Mock token exchange
const mockExchangeCodeForToken = async (
provider: 'google' | 'github',
code: string
_code: string
): Promise<string> => {
// In a real implementation, we would make a POST request to the token endpoint
// with the code, client_id, client_secret, and redirect_uri
@@ -72,7 +67,7 @@ const mockExchangeCodeForToken = async (
// Mock user info retrieval
const mockGetUserInfo = async (
provider: 'google' | 'github',
accessToken: string
_accessToken: string
): Promise<{ email: string; name: string }> => {
// In a real implementation, we would make a GET request to the user info endpoint
// with the access token