Skip to content

Commit

Permalink
Merge branch 'main' into get-wallet-by-id-or-name
Browse files Browse the repository at this point in the history
  • Loading branch information
pierrelstan authored Jan 28, 2022
2 parents 73181bf + e22490f commit bb196e0
Show file tree
Hide file tree
Showing 34 changed files with 129 additions and 50 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ module.exports = {
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/await-thenable': 'error',

'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],

// naming conventions
camelcase: 'off',
'@typescript-eslint/naming-convention': [
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,3 @@ jobs:

- name: run tests
run: npm test

- name: run e2e tests
run: npm run test-e2e
2 changes: 1 addition & 1 deletion .lintstagedrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
// keep package json sorted
'package.json': 'sort-package-json',
//'package.json': 'sort-package-json',

// fomat all files recognized by prettier
'*': 'prettier --ignore-unknown --write',
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## [1.5.2](https://github.com/Greenstand/treetracker-query-api/compare/v1.5.1...v1.5.2) (2022-01-28)

### Bug Fixes

- countries should return a list ([79ebc61](https://github.com/Greenstand/treetracker-query-api/commit/79ebc61be986672ea5df72d3fbc25ab6d2fe17c2))
- return 404 when countries not found ([4f1cecb](https://github.com/Greenstand/treetracker-query-api/commit/4f1cecbc2c47544447761700c04b3bb033c16ab1))

## [1.5.1](https://github.com/Greenstand/treetracker-query-api/compare/v1.5.0...v1.5.1) (2022-01-28)

### Bug Fixes

- 404 error returned for unknown trees and countries ([c40f0e2](https://github.com/Greenstand/treetracker-query-api/commit/c40f0e2200989d6f971b922865473e1959a5c2bf))
- updated eslint config and renamed req and next params of error handler ([9723abc](https://github.com/Greenstand/treetracker-query-api/commit/9723abc0b8719c578418095051f0c0957a488a6d))

# [1.5.0](https://github.com/Greenstand/treetracker-query-api/compare/v1.4.1...v1.5.0) (2022-01-26)

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion __tests__/e2e/countries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('', () => {
'/countries?lat=36.5617653792527&lon=103.819073145824',
);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
});
Expand Down
13 changes: 13 additions & 0 deletions __tests__/e2e/trees.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ describe('trees', () => {
});
});

it('Unknown tree', async () => {
const response = await supertest(app).get('/trees/1');
expect(response.status).toBe(404);
});

it('trees?limit=1&offset=0', async () => {
const response = await supertest(app).get('/trees?limit=1&offset=0');
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
trees: expect.anything(),
});
});

it('trees?limit=1&offset=0', async () => {
const response = await supertest(app).get('/trees?limit=1&offset=0');
expect(response.status).toBe(200);
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ module.exports = {
globalSetup: '<rootDir>/.jest/globalSetup.ts',
setupFilesAfterEnv: ['<rootDir>/.jest/setupFile.ts'],
maxConcurrency: 1,
testPathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/node_modules/'],
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "treetracker-query-api",
"version": "1.5.0",
"version": "1.5.2",
"private": false,
"keywords": [
"ecology"
Expand Down
2 changes: 1 addition & 1 deletion server/infra/database/BaseRepository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Session from './Session';
const tracker = mockKnex.getTracker();

describe('BaseRepository', () => {
let baseRepository: BaseRepository<any>;
let baseRepository: BaseRepository<{ [key: string]: string | number }>;

beforeEach(() => {
mockKnex.mock(knex);
Expand Down
19 changes: 11 additions & 8 deletions server/infra/database/BaseRepository.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-restricted-syntax */
import { Knex } from 'knex';
import Filter from 'interfaces/Filter';
import HttpError from 'utils/HttpError';
import Session from './Session';

type FilterOptions = {
limit?: number;
orderBy?: { column: string; direction?: 'asc' | 'desc' };
};

export default class BaseRepository<T> {
tableName: string;

Expand Down Expand Up @@ -32,14 +39,10 @@ export default class BaseRepository<T> {
* options:
* limit: number
*/
async getByFilter(
filter: T,
options:
| {
limit?: number;
orderBy?: { column: string; direction?: 'asc' | 'desc' };
}
| undefined = undefined,

async getByFilter<FilterType>(
filter: Filter<FilterType>,
options?: FilterOptions,
) {
const whereBuilder = function (object: any, builder: Knex.QueryBuilder) {
let result = builder;
Expand Down
9 changes: 5 additions & 4 deletions server/infra/database/CountryRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Country from 'interfaces/Country';
import Filter from 'interfaces/Filter';
import HttpError from 'utils/HttpError';
import BaseRepository from './BaseRepository';
import Session from './Session';
Expand Down Expand Up @@ -28,9 +29,9 @@ export default class CountryRepository extends BaseRepository<Country> {
}

async getByFilter(
filter: any,
filter: Filter = {},
// options?: { limit?: number | undefined } | undefined,
): Promise<any[]> {
): Promise<Country[]> {
const { lat, lon } = filter;
const sql = `
SELECT
Expand All @@ -45,13 +46,13 @@ export default class CountryRepository extends BaseRepository<Country> {
type_id = 6
`;
const object = await this.session.getDB().raw(sql);
if (!object && object.rows.length !== 1) {
if (!object || object.rows.length <= 0) {
throw new HttpError(
404,
`Can not found ${this.tableName} by lat:${lat} lon:${lon}`,
);
}
return object.rows[0];
return object.rows;
}

// eslint-disable-next-line class-methods-use-this
Expand Down
3 changes: 2 additions & 1 deletion server/infra/database/OrganizationRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import FilterOptions from 'interfaces/FilterOptions';
import Organization from 'interfaces/Organization';
import BaseRepository from './BaseRepository';
import Session from './Session';
Expand All @@ -7,7 +8,7 @@ export default class OrganizationRepository extends BaseRepository<Organization>
super('entity', session);
}

async getByPlanter(planter_id: number, options: any) {
async getByPlanter(planter_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
Expand Down
3 changes: 2 additions & 1 deletion server/infra/database/PlanterRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import FilterOptions from 'interfaces/FilterOptions';
import Planter from 'interfaces/Planter';
import BaseRepository from './BaseRepository';
import Session from './Session';
Expand All @@ -7,7 +8,7 @@ export default class PlanterRepository extends BaseRepository<Planter> {
super('planter', session);
}

async getByOrganization(organization_id: number, options: any) {
async getByOrganization(organization_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
Expand Down
5 changes: 3 additions & 2 deletions server/infra/database/SpeciesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import FilterOptions from 'interfaces/FilterOptions';
import Species from 'interfaces/Species';
import BaseRepository from './BaseRepository';
import Session from './Session';
Expand All @@ -7,7 +8,7 @@ export default class SpeciesRepository extends BaseRepository<Species> {
super('tree_species', session);
}

async getByOrganization(organization_id: number, options: any) {
async getByOrganization(organization_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
select species_id as id, count(species_id) as total, tree_species.name
Expand All @@ -30,7 +31,7 @@ export default class SpeciesRepository extends BaseRepository<Species> {
return object.rows;
}

async getByPlanter(planter_id: number, options: any) {
async getByPlanter(planter_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
select species_id as id, count(species_id) as total, tree_species.name
Expand Down
3 changes: 2 additions & 1 deletion server/infra/database/TreeRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import FilterOptions from 'interfaces/FilterOptions';
import Tree from 'interfaces/Tree';
import BaseRepository from './BaseRepository';
import Session from './Session';
Expand All @@ -7,7 +8,7 @@ export default class TreeRepository extends BaseRepository<Tree> {
super('trees', session);
}

async getByOrganization(organization_id: number, options: any) {
async getByOrganization(organization_id: number, options: FilterOptions) {
const { limit, offset } = options;
const sql = `
SELECT
Expand Down
10 changes: 8 additions & 2 deletions server/infra/database/delegateRepository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
export function delegateRepository<Type>(methodName: string): (r: any) => any {
return function (repo: Type) {
type RepoFunction<RepoType, ResultType> = (
repo: RepoType,
) => (...args: unknown[]) => Promise<ResultType>;

export function delegateRepository<T, T2>(
methodName: string,
): RepoFunction<T, T2> {
return function (repo: T) {
return async function (...args) {
const result = await repo[methodName](...args);
return result;
Expand Down
8 changes: 8 additions & 0 deletions server/interfaces/Filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type Filter<T = unknown> = {
planter_id?: number;
organization_id?: number;
lat?: number;
lon?: number;
} & T;

export default Filter;
3 changes: 3 additions & 0 deletions server/interfaces/FilterOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type FilterOptions = { limit?: number; offset?: number };

export default FilterOptions;
5 changes: 5 additions & 0 deletions server/interfaces/Organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ export default interface Organization {
id: number;
first_name: string;
last_name: string;
links: {
featured_trees: string;
associated_planters: string;
species: string;
};
}
5 changes: 5 additions & 0 deletions server/interfaces/Planter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ export default interface Planter {
id: number;
first_name: string;
last_name: string;
links: {
featured_trees: string;
associated_organizations: string;
species: string;
};
}
13 changes: 8 additions & 5 deletions server/models/Country.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import Country from 'interfaces/Country';
import Filter from 'interfaces/Filter';
import CountryRepository from '../infra/database/CountryRepository';
import { delegateRepository } from '../infra/database/delegateRepository';

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

export default {
getCountries,
getById: delegateRepository<CountryRepository>('getById'),
getByFilter: delegateRepository<CountryRepository>('getByFilter'),
getLeaderBoard: delegateRepository<CountryRepository>('getLeaderBoard'),
getById: delegateRepository<CountryRepository, Country>('getById'),
getByFilter: delegateRepository<CountryRepository, Country>('getByFilter'),
getLeaderBoard: delegateRepository<CountryRepository, Country>(
'getLeaderBoard',
),
};
8 changes: 5 additions & 3 deletions server/models/Organization.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import log from 'loglevel';
import Filter from 'interfaces/Filter';
import FilterOptions from 'interfaces/FilterOptions';
import Organization from 'interfaces/Organization';
import { delegateRepository } from '../infra/database/delegateRepository';
import OrganizationRepository from '../infra/database/OrganizationRepository';

function getByFilter(
organizationRepository: OrganizationRepository,
): (filter: any, options: any) => Promise<Organization[]> {
return async function (filter: any, options: any) {
): (filter: Filter, options: FilterOptions) => Promise<Organization[]> {
return async function (filter: Filter, options: FilterOptions) {
if (filter.planter_id) {
log.warn('using planter filter...');
const trees = await organizationRepository.getByPlanter(
Expand All @@ -30,7 +32,7 @@ function getOrganizationLinks(organization) {
}

export default {
getById: delegateRepository<OrganizationRepository>('getById'),
getById: delegateRepository<OrganizationRepository, Organization>('getById'),
getByFilter,
getOrganizationLinks,
};
8 changes: 5 additions & 3 deletions server/models/Planter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import log from 'loglevel';
import Filter from 'interfaces/Filter';
import FilterOptions from 'interfaces/FilterOptions';
import Planter from 'interfaces/Planter';
import { delegateRepository } from '../infra/database/delegateRepository';
import PlanterRepository from '../infra/database/PlanterRepository';

function getByFilter(
planterRepository: PlanterRepository,
): (filter: any, options: any) => Promise<Planter[]> {
return async function (filter: any, options: any) {
): (filter: Filter, options: FilterOptions) => Promise<Planter[]> {
return async function (filter: Filter, options: FilterOptions) {
if (filter.organization_id) {
log.warn('using org filter...');
const trees = await planterRepository.getByOrganization(
Expand All @@ -30,7 +32,7 @@ function getPlanterLinks(planter) {
}

export default {
getById: delegateRepository<PlanterRepository>('getById'),
getById: delegateRepository<PlanterRepository, Planter>('getById'),
getByFilter,
getPlanterLinks,
};
8 changes: 5 additions & 3 deletions server/models/Species.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import log from 'loglevel';
import Filter from 'interfaces/Filter';
import FilterOptions from 'interfaces/FilterOptions';
import Species from 'interfaces/Species';
import { delegateRepository } from '../infra/database/delegateRepository';
import SpeciesRepository from '../infra/database/SpeciesRepository';

function getByFilter(
speciesRepository: SpeciesRepository,
): (filter: any, options: any) => Promise<Species[]> {
return async function (filter: any, options: any) {
): (filter: Filter, options: FilterOptions) => Promise<Species[]> {
return async function (filter: Filter, options: FilterOptions) {
if (filter.organization_id) {
log.warn('using org filter...');
const trees = await speciesRepository.getByOrganization(
Expand All @@ -29,6 +31,6 @@ function getByFilter(
}

export default {
getById: delegateRepository<SpeciesRepository>('getById'),
getById: delegateRepository<SpeciesRepository, Species>('getById'),
getByFilter,
};
Loading

0 comments on commit bb196e0

Please sign in to comment.