Fix GitHub Actions build by adding missing repository files
The build was failing because repository files were ignored by .gitignore: - backend/src/features/*/data/*.repository.ts files were excluded by 'data/' pattern - These files exist locally but were missing in CI, causing TS2307 module errors - Controllers and services import these repositories, causing cascade failures Changes: - Updated .gitignore to allow TypeScript files in feature data directories - Added fuel-logs.repository.ts, stations.repository.ts, vehicles.repository.ts - Docker build now succeeds (tested with --no-cache) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
117
backend/src/features/stations/data/stations.repository.ts
Normal file
117
backend/src/features/stations/data/stations.repository.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @ai-summary Data access layer for stations
|
||||
*/
|
||||
|
||||
import { Pool } from 'pg';
|
||||
import { Station, SavedStation } from '../domain/stations.types';
|
||||
|
||||
export class StationsRepository {
|
||||
constructor(private pool: Pool) {}
|
||||
|
||||
async cacheStation(station: Station): Promise<void> {
|
||||
const query = `
|
||||
INSERT INTO station_cache (
|
||||
place_id, name, address, latitude, longitude,
|
||||
price_regular, price_premium, price_diesel, rating, photo_url
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
ON CONFLICT (place_id) DO UPDATE
|
||||
SET name = $2, address = $3, latitude = $4, longitude = $5,
|
||||
rating = $9, photo_url = $10, cached_at = NOW()
|
||||
`;
|
||||
|
||||
await this.pool.query(query, [
|
||||
station.placeId,
|
||||
station.name,
|
||||
station.address,
|
||||
station.latitude,
|
||||
station.longitude,
|
||||
station.priceRegular,
|
||||
station.pricePremium,
|
||||
station.priceDiesel,
|
||||
station.rating,
|
||||
station.photoUrl
|
||||
]);
|
||||
}
|
||||
|
||||
async getCachedStation(placeId: string): Promise<Station | null> {
|
||||
const query = 'SELECT * FROM station_cache WHERE place_id = $1';
|
||||
const result = await this.pool.query(query, [placeId]);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.mapCacheRow(result.rows[0]);
|
||||
}
|
||||
|
||||
async saveStation(userId: string, placeId: string, data?: { nickname?: string; notes?: string; isFavorite?: boolean }): Promise<SavedStation> {
|
||||
const query = `
|
||||
INSERT INTO saved_stations (user_id, place_id, nickname, notes, is_favorite)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
ON CONFLICT (user_id, place_id) DO UPDATE
|
||||
SET nickname = COALESCE($3, saved_stations.nickname),
|
||||
notes = COALESCE($4, saved_stations.notes),
|
||||
is_favorite = COALESCE($5, saved_stations.is_favorite),
|
||||
updated_at = NOW()
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const result = await this.pool.query(query, [
|
||||
userId,
|
||||
placeId,
|
||||
data?.nickname,
|
||||
data?.notes,
|
||||
data?.isFavorite || false
|
||||
]);
|
||||
|
||||
return this.mapSavedRow(result.rows[0]);
|
||||
}
|
||||
|
||||
async getUserSavedStations(userId: string): Promise<SavedStation[]> {
|
||||
const query = `
|
||||
SELECT * FROM saved_stations
|
||||
WHERE user_id = $1
|
||||
ORDER BY is_favorite DESC, created_at DESC
|
||||
`;
|
||||
|
||||
const result = await this.pool.query(query, [userId]);
|
||||
return result.rows.map(row => this.mapSavedRow(row));
|
||||
}
|
||||
|
||||
async deleteSavedStation(userId: string, placeId: string): Promise<boolean> {
|
||||
const query = 'DELETE FROM saved_stations WHERE user_id = $1 AND place_id = $2';
|
||||
const result = await this.pool.query(query, [userId, placeId]);
|
||||
return (result.rowCount ?? 0) > 0;
|
||||
}
|
||||
|
||||
private mapCacheRow(row: any): Station {
|
||||
return {
|
||||
id: row.id,
|
||||
placeId: row.place_id,
|
||||
name: row.name,
|
||||
address: row.address,
|
||||
latitude: parseFloat(row.latitude),
|
||||
longitude: parseFloat(row.longitude),
|
||||
priceRegular: row.price_regular ? parseFloat(row.price_regular) : undefined,
|
||||
pricePremium: row.price_premium ? parseFloat(row.price_premium) : undefined,
|
||||
priceDiesel: row.price_diesel ? parseFloat(row.price_diesel) : undefined,
|
||||
rating: row.rating ? parseFloat(row.rating) : undefined,
|
||||
photoUrl: row.photo_url,
|
||||
lastUpdated: row.cached_at
|
||||
};
|
||||
}
|
||||
|
||||
private mapSavedRow(row: any): SavedStation {
|
||||
return {
|
||||
id: row.id,
|
||||
userId: row.user_id,
|
||||
stationId: row.place_id,
|
||||
nickname: row.nickname,
|
||||
notes: row.notes,
|
||||
isFavorite: row.is_favorite,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user