65 create map endpoint to get users or clusters corresponding the current coords zoom#66
Conversation
YoungMame
commented
Dec 27, 2025
There was a problem hiding this comment.
Pull request overview
This PR implements a new /private/map endpoint that returns users or location clusters based on geographic coordinates and zoom level. The endpoint supports three levels: level 0 returns individual users, level 1 returns city-level clusters, and level 2 returns country-level clusters. The implementation includes comprehensive integration tests and follows the existing service/controller/route architecture pattern.
- Adds MapService to handle geolocation-based queries with distance calculations using the Haversine formula
- Implements new User model methods for fetching users and user count clusters by location
- Creates endpoint with query parameter validation for level, latitude, longitude, and radius
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 24 comments.
Show a summary per file
| File | Description |
|---|---|
| fastify/assets/test/integration/ws/like.test.ts | Removes debug console.log statement |
| fastify/assets/test/integration/private/map.test.ts | Adds comprehensive integration tests for all three map levels |
| fastify/assets/srcs/services/MapService.ts | Creates new service with validation and business logic for location-based queries |
| fastify/assets/srcs/routes/private/map/index.ts | Defines route schema and query parameter validation for the map endpoint |
| fastify/assets/srcs/routes/private/index.ts | Registers the new map routes under /private/map prefix |
| fastify/assets/srcs/models/User/index.ts | Adds getUsersFromLocation and getUsersCountByLocation methods with geospatial queries |
| fastify/assets/srcs/controllers/private/map/index.ts | Implements request handler with authentication and error handling |
| fastify/assets/srcs/app.ts | Registers the MapService plugin with the Fastify instance |
| fastify/assets/@types/fastify.d.ts | Adds TypeScript type definitions for the mapService interface |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return []; | ||
|
|
||
| const result = await this.fastify.pg.query( | ||
| `SELECT count(${areaName}) AS count, avg(latitude) AS latitude, avg(longitude) AS longitude |
There was a problem hiding this comment.
The COUNT aggregation is counting occurrences of the column value (city or country) rather than counting rows. This should use COUNT(*) or COUNT(user_id) to count the number of users per location cluster, not the number of non-null city/country values. The current query may produce incorrect counts.
| `SELECT count(${areaName}) AS count, avg(latitude) AS latitude, avg(longitude) AS longitude | |
| `SELECT count(*) AS count, avg(latitude) AS latitude, avg(longitude) AS longitude |
| 400: { | ||
| type: 'object', | ||
| properties: { | ||
| message: { type: 'string', } |
There was a problem hiding this comment.
The error response schema expects a 'message' property for 400 errors, but the controller sends an 'error' property on line 24 of the controller. Update the schema to use 'error' instead of 'message' for consistency with the actual error response format.
| message: { type: 'string', } | |
| error: { type: 'string', } |
| // import utils | ||
| import { setLocalisation } from '../utils/browsing'; | ||
|
|
||
| describe('User picture integration tests', async () => { |
There was a problem hiding this comment.
The test suite description says "User picture integration tests" but the tests are for the map endpoint functionality. Update the description to accurately reflect what is being tested, such as "Map endpoint integration tests".
| describe('User picture integration tests', async () => { | |
| describe('Map endpoint integration tests', async () => { |
| if (level != 0 && level != 1 && level != 2) | ||
| throw new BadRequestError(); | ||
| if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180 || radius < 0) | ||
| throw new BadRequestError(); |
There was a problem hiding this comment.
Use strict equality operators (=== and !==) instead of loose equality operators (== and !=). This follows JavaScript best practices and prevents potential type coercion issues.
| users: [] as MapUser[], | ||
| clusters: [] as MapUserCluster[] | ||
| } | ||
| if (level == 0) |
There was a problem hiding this comment.
Use strict equality operators (=== and !==) instead of loose equality (==). The same issue appears in the ternary operator on line 142.
|
|
||
| it('should be able to fetch user on level 1', async () => { | ||
| const { userData: data1, token: token1 } = await quickUser(app); | ||
| const { userData: data2, token: token2 } = await quickUser(app); |
There was a problem hiding this comment.
Unused variable data2.
| it('should be able to fetch user on level 1', async () => { | ||
| const { userData: data1, token: token1 } = await quickUser(app); | ||
| const { userData: data2, token: token2 } = await quickUser(app); | ||
| const { userData: data3, token: token3 } = await quickUser(app); |
There was a problem hiding this comment.
Unused variable data3.
| }); | ||
|
|
||
| it('should be able to fetch user on level 2', async () => { | ||
| const { userData: data1, token: token1 } = await quickUser(app); |
There was a problem hiding this comment.
Unused variable data1.
|
|
||
| it('should be able to fetch user on level 2', async () => { | ||
| const { userData: data1, token: token1 } = await quickUser(app); | ||
| const { userData: data2, token: token2 } = await quickUser(app); |
There was a problem hiding this comment.
Unused variable data2.
| it('should be able to fetch user on level 2', async () => { | ||
| const { userData: data1, token: token1 } = await quickUser(app); | ||
| const { userData: data2, token: token2 } = await quickUser(app); | ||
| const { userData: data3, token: token3 } = await quickUser(app); |
There was a problem hiding this comment.
Unused variable data3.