Initial Commit

This commit is contained in:
Eric Gullickson
2025-09-17 16:09:15 -05:00
parent 0cdb9803de
commit a052040e3a
373 changed files with 437090 additions and 6773 deletions

View File

@@ -1,14 +1,13 @@
# Ustations Feature Capsule
# Stations Feature Capsule
## Quick Summary (50 tokens)
[AI: Complete feature description, main operations, dependencies, caching strategy]
## Summary
Search nearby gas stations via Google Maps and manage users' saved stations.
## API Endpoints
- GET /api/stations - List all stations
- GET /api/stations/:id - Get specific lUstations
- POST /api/stations - Create new lUstations
- PUT /api/stations/:id - Update lUstations
- DELETE /api/stations/:id - Delete lUstations
## API Endpoints (JWT required)
- `POST /api/stations/search` — Search nearby stations
- `POST /api/stations/save` — Save a station to user's favorites
- `GET /api/stations/saved` — List saved stations for the user
- `DELETE /api/stations/saved/:placeId` — Remove a saved station
## Structure
- **api/** - HTTP endpoints, routes, validators
@@ -22,7 +21,7 @@
## Dependencies
- Internal: core/auth, core/cache
- External: [List any external APIs]
- External: Google Maps API (Places)
- Database: stations table
## Quick Commands
@@ -33,3 +32,9 @@ npm test -- features/stations
# Run feature migrations
npm run migrate:feature stations
```
## Clarifications Needed
- Search payload structure (required fields, radius/filters)?
- Saved station schema and required fields?
- Caching policy for searches (TTL, cache keys)?
- Rate limits or quotas for Google Maps calls?

View File

@@ -11,6 +11,7 @@ import {
StationParams
} from '../domain/stations.types';
import { StationsController } from './stations.controller';
import { tenantMiddleware } from '../../../core/middleware/tenant';
export const stationsRoutes: FastifyPluginAsync = async (
fastify: FastifyInstance,
@@ -20,25 +21,25 @@ export const stationsRoutes: FastifyPluginAsync = async (
// POST /api/stations/search - Search nearby stations
fastify.post<{ Body: StationSearchBody }>('/stations/search', {
preHandler: fastify.authenticate,
preHandler: [fastify.authenticate, tenantMiddleware],
handler: stationsController.searchStations.bind(stationsController)
});
// POST /api/stations/save - Save a station to user's favorites
fastify.post<{ Body: SaveStationBody }>('/stations/save', {
preHandler: fastify.authenticate,
preHandler: [fastify.authenticate, tenantMiddleware],
handler: stationsController.saveStation.bind(stationsController)
});
// GET /api/stations/saved - Get user's saved stations
fastify.get('/stations/saved', {
preHandler: fastify.authenticate,
preHandler: [fastify.authenticate, tenantMiddleware],
handler: stationsController.getSavedStations.bind(stationsController)
});
// DELETE /api/stations/saved/:placeId - Remove saved station
fastify.delete<{ Params: StationParams }>('/stations/saved/:placeId', {
preHandler: fastify.authenticate,
preHandler: [fastify.authenticate, tenantMiddleware],
handler: stationsController.removeSavedStation.bind(stationsController)
});
};
@@ -46,4 +47,4 @@ export const stationsRoutes: FastifyPluginAsync = async (
// For backward compatibility during migration
export function registerStationsRoutes() {
throw new Error('registerStationsRoutes is deprecated - use stationsRoutes Fastify plugin instead');
}
}

View File

@@ -30,14 +30,15 @@ CREATE TABLE IF NOT EXISTS saved_stations (
);
-- Create indexes
CREATE INDEX idx_station_cache_place_id ON station_cache(place_id);
CREATE INDEX idx_station_cache_location ON station_cache(latitude, longitude);
CREATE INDEX idx_station_cache_cached_at ON station_cache(cached_at);
CREATE INDEX IF NOT EXISTS idx_station_cache_place_id ON station_cache(place_id);
CREATE INDEX IF NOT EXISTS idx_station_cache_location ON station_cache(latitude, longitude);
CREATE INDEX IF NOT EXISTS idx_station_cache_cached_at ON station_cache(cached_at);
CREATE INDEX idx_saved_stations_user_id ON saved_stations(user_id);
CREATE INDEX idx_saved_stations_is_favorite ON saved_stations(is_favorite);
CREATE INDEX IF NOT EXISTS idx_saved_stations_user_id ON saved_stations(user_id);
CREATE INDEX IF NOT EXISTS idx_saved_stations_is_favorite ON saved_stations(is_favorite);
-- Add trigger for updated_at
DROP TRIGGER IF EXISTS update_saved_stations_updated_at ON saved_stations;
CREATE TRIGGER update_saved_stations_updated_at
BEFORE UPDATE ON saved_stations
FOR EACH ROW