Skip to content

Commit

Permalink
Merge pull request #95 from dagmawig/main
Browse files Browse the repository at this point in the history
feat: implement countries/v2 and countries/v2/[id]
  • Loading branch information
dadiorchen authored Mar 18, 2022
2 parents 50d5da2 + 2067e6f commit eba8821
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
21 changes: 21 additions & 0 deletions __tests__/e2e/countries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ describe('', () => {
});
});

it('countries/v2/6632544', async () => {
const response = await supertest(app).get('/countries/v2/6632544');
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 6632544,
name: 'China',
});
});

// 103.819073145824,36.5617653792527
it('countries/v2/?lat=36.5617653792527&lon=103.819073145824', async () => {
const response = await supertest(app).get(
'/countries/v2/?lat=36.5617653792527&lon=103.819073145824',
);
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
});
});

it(
'countries/leaderboard',
async () => {
Expand Down
61 changes: 61 additions & 0 deletions server/infra/database/CountryRepositoryV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Country from 'interfaces/Country';
import HttpError from 'utils/HttpError';
import BaseRepository from './BaseRepository';
import Session from './Session';

type Filter = Partial<{ lat: number; lon: number }>;

export default class CountryRepositoryV2 extends BaseRepository<Country> {
constructor(session: Session) {
super('region', session);
}

async getById(id: string | number) {
const object = await this.session
.getDB()
.select(
this.session.getDB().raw(`
id,
name,
St_asgeojson(centroid) as centroid
`),
)
.table(this.tableName)
.where('id', id)
.first();
if (!object) {
throw new HttpError(404, `Can not found ${this.tableName} by id:${id}`);
}
return object;
}

async getByFilter(
filter: Filter,
// options?: { limit?: number | undefined } | undefined,
): Promise<Country[]> {
const { lat, lon } = filter;
const sql = `
WITH country_id AS (
select id from region_type where type = 'country'
)
SELECT
id,
name,
St_asgeojson(centroid) as centroid
FROM
region
WHERE
ST_Contains(geom, ST_GeomFromText('POINT(${lon} ${lat})', 4326)) = true
AND
type_id in (select id from country_id);
`;
const object = await this.session.getDB().raw(sql);
if (!object || object.rows.length <= 0) {
throw new HttpError(
404,
`Can not found ${this.tableName} by lat:${lat} lon:${lon}`,
);
}
return object.rows;
}
}
20 changes: 20 additions & 0 deletions server/models/CountryV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import CountryRepositoryV2 from 'infra/database/CountryRepositoryV2';
import Country from 'interfaces/Country';
import { delegateRepository } from '../infra/database/delegateRepository';

type Filter = Partial<{ lat: number; lon: number }>;

function getCountries(
countryRepository: CountryRepositoryV2,
): (filter: Filter) => Promise<Country[]> {
return async function (filter: Filter) {
const countries = await countryRepository.getByFilter(filter);
return countries;
};
}

export default {
getCountries,
getById: delegateRepository<CountryRepositoryV2, Country>('getById'),
getByFilter: delegateRepository<CountryRepositoryV2, Country>('getByFilter'),
};
35 changes: 35 additions & 0 deletions server/routers/countriesRouter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,47 @@
import express from 'express';
import Joi from 'joi';
import CountryRepositoryV2 from 'infra/database/CountryRepositoryV2';
import { handlerWrapper } from './utils';
import CountryRepository from '../infra/database/CountryRepository';
import Session from '../infra/database/Session';
import CountryModel from '../models/Country';
import CountryModelV2 from '../models/CountryV2';

const router = express.Router();

router.get(
'/v2/:id',
handlerWrapper(async (req, res) => {
Joi.assert(req.params.id, Joi.number().required());
const repo = new CountryRepositoryV2(new Session());
const exe = CountryModelV2.getById(repo);
const result = await exe(req.params.id);
res.send(result);
res.end();
}),
);

router.get(
'/v2/',
handlerWrapper(async (req, res) => {
Joi.assert(
req.query,
Joi.object().keys({
limit: Joi.number().integer().min(1).max(1000),
offset: Joi.number().integer().min(0),
lat: Joi.number(),
lon: Joi.number(),
}),
);
const repo = new CountryRepositoryV2(new Session());
const result = await CountryModelV2.getByFilter(repo)(req.query);
res.send({
countries: result,
});
res.end();
}),
);

router.get(
'/leaderboard',
handlerWrapper(async (req, res) => {
Expand Down

0 comments on commit eba8821

Please sign in to comment.