Compare commits

...

2 Commits

Author SHA1 Message Date
5a44c81b8e
Merge branch 'master' of git.icynet.eu:evert/geobase 2023-07-29 09:57:53 +03:00
d2d8e5fb24
stash changes 2023-07-29 09:57:40 +03:00
8 changed files with 74 additions and 5 deletions

View File

@ -9,8 +9,8 @@ export class CountriesController {
constructor(private readonly service: CountriesService) {} constructor(private readonly service: CountriesService) {}
@Get() @Get()
async getAllCountries(@Query() { q, fields }: CountriesQueryDto) { async getAllCountries(@Query() query: CountriesQueryDto) {
return this.service.search(q, fields); return this.service.search(query);
} }
@Get(':iso') @Get(':iso')

View File

@ -1,4 +1,6 @@
export interface CountriesQueryDto { export interface CountriesQueryDto {
fields?: string[]; fields?: string[];
q?: string; q?: string;
limit?: string;
offset?: string;
} }

View File

@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { ILike, Repository } from 'typeorm'; import { ILike, Repository } from 'typeorm';
import { Country } from './countries.entity'; import { Country } from './countries.entity';
import { intOrNull } from 'src/utils/int-or-null'; import { intOrNull } from 'src/utils/int-or-null';
import { CountriesQueryDto } from './countries.interfaces';
const COUNTRIES_URL = const COUNTRIES_URL =
'https://download.geonames.org/export/dump/countryInfo.txt'; 'https://download.geonames.org/export/dump/countryInfo.txt';
@ -83,9 +84,17 @@ export class CountriesService {
}); });
} }
async search(query?: string, fields = ACCEPT_FIELDS) { async search({
q: query,
fields = ACCEPT_FIELDS,
limit,
offset,
}: CountriesQueryDto) {
const select = this.mapAllowedQuery(fields); const select = this.mapAllowedQuery(fields);
const filter = {}; const filter = {};
const take = Math.max(Math.min(intOrNull(limit as string) || 50, 1000), 1);
const skip = intOrNull(offset as string) || 0;
if (query) { if (query) {
filter['country'] = ILike(`%${query}%`); filter['country'] = ILike(`%${query}%`);
@ -94,6 +103,8 @@ export class CountriesService {
return this.countryRepository.find({ return this.countryRepository.find({
where: filter, where: filter,
select, select,
skip,
take,
}); });
} }

View File

@ -1,5 +1,5 @@
import { Controller, Get, Query } from '@nestjs/common'; import { Controller, Get, Query } from '@nestjs/common';
import { GeonameQuery } from './geonames.interfaces'; import { FeatureQuery, GeonameQuery } from './geonames.interfaces';
import { GeonamesService } from './geonames.service'; import { GeonamesService } from './geonames.service';
@Controller({ @Controller({
@ -12,4 +12,9 @@ export class GeonamesController {
async search(@Query() query: GeonameQuery) { async search(@Query() query: GeonameQuery) {
return this.service.search(query); return this.service.search(query);
} }
@Get('features')
async features(@Query() query: FeatureQuery) {
return this.service.getFeatureList(query);
}
} }

View File

@ -11,3 +11,8 @@ export type GeonameQuery = Record<keyof Geoname, unknown> & {
offset?: string; offset?: string;
q?: string; q?: string;
}; };
export interface FeatureQuery {
q?: string;
class?: string;
}

View File

@ -3,12 +3,17 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { DataSource, ILike, In, Repository } from 'typeorm'; import { DataSource, ILike, In, Repository } from 'typeorm';
import { pipeline } from 'stream/promises'; import { pipeline } from 'stream/promises';
import { join } from 'path'; import { join } from 'path';
import { GeonameQuery, WorkDirectory } from './geonames.interfaces'; import {
FeatureQuery,
GeonameQuery,
WorkDirectory,
} from './geonames.interfaces';
import { createInterface } from 'readline'; import { createInterface } from 'readline';
import { Geoname } from './geonames.entity'; import { Geoname } from './geonames.entity';
import { intOrNull } from 'src/utils/int-or-null'; import { intOrNull } from 'src/utils/int-or-null';
import * as fs from 'fs'; import * as fs from 'fs';
import * as unzipper from 'unzipper'; import * as unzipper from 'unzipper';
import { GeoFeature } from './feature.dictionary';
const GEONAMES_DUMP = const GEONAMES_DUMP =
'https://download.geonames.org/export/dump/allCountries.zip'; 'https://download.geonames.org/export/dump/allCountries.zip';
@ -216,4 +221,33 @@ export class GeonamesService {
Logger.log('Done!', context); Logger.log('Done!', context);
} }
getFeatureList({ q, class: className }: FeatureQuery) {
return Object.keys(GeoFeature)
.filter((code) => {
if (!className) return true;
return GeoFeature[code][0] === className.toUpperCase();
})
.filter((code) => {
if (!q) return true;
const lower = q.toLowerCase();
return (
code.includes(lower) ||
GeoFeature[code][1]?.includes(lower) ||
GeoFeature[code][2]?.includes(lower)
);
})
.reduce(
(prev, curr) => [
...prev,
{
code: curr,
class: GeoFeature[curr][0],
name: GeoFeature[curr][1],
description: GeoFeature[curr][2],
},
],
[],
);
}
} }

View File

@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { TimezonesService } from './timezones.service';
@Module({
providers: [TimezonesService],
exports: [TimezonesService],
})
export class TimezonesModule {}

View File

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class TimezonesService {}