mirror of
https://github.com/FoggedLens/deflock.git
synced 2026-07-30 15:39:06 +02:00
Multi Geocode (#109)
* multi-geocode for new map * backward compatibility w/ city polygon
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ bun install
|
|||||||
|
|
||||||
### Run locally
|
### Run locally
|
||||||
```sh
|
```sh
|
||||||
bun server.ts
|
bun dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"main": "server.ts",
|
"main": "server.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev": "NODE_ENV=development bun server.ts",
|
||||||
"start": "bun server.ts"
|
"start": "bun server.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+32
-5
@@ -34,11 +34,12 @@ const start = async () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Coors Light Config
|
// Coors Banquet Config
|
||||||
await server.register(cors, {
|
await server.register(cors, {
|
||||||
origin: (origin, cb) => {
|
origin: (origin, cb) => {
|
||||||
const allowedOrigins = [
|
const allowedOrigins = [
|
||||||
'http://localhost:5173', // vite dev server
|
'http://localhost:5173', // DeFlock Legacy
|
||||||
|
'http://localhost:3000', // FlockHopper
|
||||||
'https://deflock.org',
|
'https://deflock.org',
|
||||||
'https://www.deflock.org'
|
'https://www.deflock.org'
|
||||||
];
|
];
|
||||||
@@ -80,11 +81,35 @@ const start = async () => {
|
|||||||
},
|
},
|
||||||
}, async (request, reply) => {
|
}, async (request, reply) => {
|
||||||
const { query } = request.query as { query: string };
|
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);
|
const result = await nominatim.geocodeSingleResult(query);
|
||||||
return result;
|
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', {
|
server.get('/sponsors/github', {
|
||||||
schema: {
|
schema: {
|
||||||
querystring: {
|
querystring: {
|
||||||
@@ -110,8 +135,10 @@ const start = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await server.listen({ host: '0.0.0.0', port: 3000 });
|
const defaultPort = process.env.NODE_ENV === 'development' ? 3420 : 3000;
|
||||||
console.log('Server listening on port 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) {
|
} catch (err) {
|
||||||
console.error('Failed to start server:', err);
|
console.error('Failed to start server:', err);
|
||||||
server.log.error(err);
|
server.log.error(err);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ export const NominatimResultSchema = Type.Object({
|
|||||||
boundingbox: Type.Tuple([Type.String(), Type.String(), Type.String(), Type.String()]),
|
boundingbox: Type.Tuple([Type.String(), Type.String(), Type.String(), Type.String()]),
|
||||||
class: Type.String(),
|
class: Type.String(),
|
||||||
display_name: Type.String(),
|
display_name: Type.String(),
|
||||||
geojson: Type.Object({
|
geojson: Type.Optional(Type.Object({
|
||||||
coordinates: Type.Any(),
|
coordinates: Type.Any(),
|
||||||
type: Type.String(),
|
type: Type.String(),
|
||||||
}),
|
})),
|
||||||
importance: Type.Number(),
|
importance: Type.Number(),
|
||||||
lat: Type.String(),
|
lat: Type.String(),
|
||||||
licence: Type.String(),
|
licence: Type.String(),
|
||||||
@@ -39,16 +39,17 @@ const cache: Cache = createCache({
|
|||||||
export class NominatimClient {
|
export class NominatimClient {
|
||||||
baseUrl = 'https://nominatim.openstreetmap.org/search';
|
baseUrl = 'https://nominatim.openstreetmap.org/search';
|
||||||
|
|
||||||
async geocodePhrase(query: string): Promise<NominatimResult[]> {
|
async geocodePhrase(query: string, includeGeoJson: boolean = false): Promise<NominatimResult[]> {
|
||||||
const cacheKey = `geocode:${query}`;
|
const cacheKey = `geocode:${query}`;
|
||||||
const cached = await cache.get(cacheKey);
|
const cached = await cache.get(cacheKey);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
return cached as NominatimResult[];
|
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, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'DeFlock/1.1',
|
'User-Agent': 'DeFlock/1.2',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -60,7 +61,7 @@ export class NominatimClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async geocodeSingleResult(query: string): Promise<NominatimResult | null> {
|
async geocodeSingleResult(query: string): Promise<NominatimResult | null> {
|
||||||
const results = await this.geocodePhrase(query);
|
const results = await this.geocodePhrase(query, true);
|
||||||
|
|
||||||
if (!results.length) return null;
|
if (!results.length) return null;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user