diff --git a/api/README.md b/api/README.md index 2a9f414..d2281d1 100644 --- a/api/README.md +++ b/api/README.md @@ -19,7 +19,7 @@ bun install ### Run locally ```sh -bun server.ts +bun dev ``` ## Deployment diff --git a/api/package.json b/api/package.json index 4fa13b6..8a9e0c9 100644 --- a/api/package.json +++ b/api/package.json @@ -4,6 +4,7 @@ "main": "server.ts", "type": "module", "scripts": { + "dev": "NODE_ENV=development bun server.ts", "start": "bun server.ts" }, "dependencies": { diff --git a/api/server.ts b/api/server.ts index 0f26009..67d011a 100644 --- a/api/server.ts +++ b/api/server.ts @@ -34,13 +34,15 @@ const start = async () => { }); }); - // Coors Light Config + // Coors Banquet Config await server.register(cors, { origin: (origin, cb) => { const allowedOrigins = [ - 'http://localhost:5173', // vite dev server + 'http://localhost:5173', // DeFlock Legacy + 'http://localhost:3000', // FlockHopper 'https://deflock.org', - 'https://www.deflock.org' + 'https://www.deflock.org', + 'https://maps.deflock.org' ]; if (!origin || allowedOrigins.includes(origin) || /^https:\/\/.*\.deflock\.pages\.dev$/.test(origin)) { @@ -80,11 +82,35 @@ const start = async () => { }, }, async (request, reply) => { const { query } = request.query as { query: string }; - reply.header('Cache-Control', 'public, max-age=300, s-maxage=86400'); + reply.header('Cache-Control', 'public, max-age=86400, s-maxage=86400'); const result = await nominatim.geocodeSingleResult(query); return result; }); + server.get('/geocode/multi', { + schema: { + querystring: { + type: 'object', + properties: { + query: { type: 'string' }, + }, + required: ['query'], + }, + response: { + 200: { + type: 'array', + items: NominatimResultSchema, + }, + 500: { type: 'object', properties: { error: { type: 'string' } } }, + }, + }, + }, async (request, reply) => { + const { query } = request.query as { query: string }; + reply.header('Cache-Control', 'public, max-age=86400, s-maxage=86400'); + const result = await nominatim.geocodePhrase(query); + return result; + }); + server.get('/sponsors/github', { schema: { querystring: { @@ -110,8 +136,10 @@ const start = async () => { }); try { - await server.listen({ host: '0.0.0.0', port: 3000 }); - console.log('Server listening on port 3000'); + const defaultPort = process.env.NODE_ENV === 'development' ? 3420 : 3000; + const port = process.env.PORT ? parseInt(process.env.PORT, 10) : defaultPort; + await server.listen({ host: '0.0.0.0', port }); + console.log(`Server listening on port ${port}`); } catch (err) { console.error('Failed to start server:', err); server.log.error(err); diff --git a/api/services/NominatimClient.ts b/api/services/NominatimClient.ts index d0f377e..529302b 100644 --- a/api/services/NominatimClient.ts +++ b/api/services/NominatimClient.ts @@ -8,10 +8,10 @@ export const NominatimResultSchema = Type.Object({ boundingbox: Type.Tuple([Type.String(), Type.String(), Type.String(), Type.String()]), class: Type.String(), display_name: Type.String(), - geojson: Type.Object({ + geojson: Type.Optional(Type.Object({ coordinates: Type.Any(), type: Type.String(), - }), + })), importance: Type.Number(), lat: Type.String(), licence: Type.String(), @@ -39,16 +39,17 @@ const cache: Cache = createCache({ export class NominatimClient { baseUrl = 'https://nominatim.openstreetmap.org/search'; - async geocodePhrase(query: string): Promise { + async geocodePhrase(query: string, includeGeoJson: boolean = false): Promise { const cacheKey = `geocode:${query}`; const cached = await cache.get(cacheKey); if (cached) { return cached as NominatimResult[]; } - const url = `${this.baseUrl}?q=${encodeURIComponent(query)}&polygon_geojson=1&format=json`; + const geojsonParam = includeGeoJson ? '&polygon_geojson=1' : ''; + const url = `${this.baseUrl}?q=${encodeURIComponent(query)}&format=json&addressdetails=1&limit=8&countrycodes=us&dedupe=1${geojsonParam}`; const response = await fetch(url, { headers: { - 'User-Agent': 'DeFlock/1.1', + 'User-Agent': 'DeFlock/1.2', }, }); if (!response.ok) { @@ -60,7 +61,7 @@ export class NominatimClient { } async geocodeSingleResult(query: string): Promise { - const results = await this.geocodePhrase(query); + const results = await this.geocodePhrase(query, true); if (!results.length) return null; diff --git a/webapp/src/views/Landing.vue b/webapp/src/views/Landing.vue index 58ebfe9..8bb6888 100644 --- a/webapp/src/views/Landing.vue +++ b/webapp/src/views/Landing.vue @@ -1,6 +1,30 @@