feature/get-places-api #2

Merged
behnam merged 26 commits from feature/get-places-api into develop 2023-05-23 09:23:56 +00:00
19 changed files with 154 additions and 19 deletions
Showing only changes of commit ccfeb2ae4b - Show all commits

2
.env.development Normal file
View File

@ -0,0 +1,2 @@
VITE_API_ORIGIN = http://176.53.196.42:6001/api/v1
VITE_API_PLACES = /place

View File

@ -1,4 +1,9 @@
type Place = {
type Places = {
placeType: string;
name: string;
qr: null;
id: string;
parentId: string | null;
};
export default Places;

View File

@ -0,0 +1,34 @@
import Places from "../entity/placeEntity";
class PlacesModel {
private placeType: string;
private name: string;
private qr: null;
private id: string;
private parentId: string | null;
constructor(store: Places) {
const { id, name, parentId, placeType, qr } = store;
this.parentId = parentId;
this.id = id;
this.qr = qr;
this.name = name;
this.placeType = placeType;
}
getData(): Places {
return {
id: this.id,
name: this.name,
parentId: this.parentId,
placeType: this.placeType,
qr: this.qr,
};
}
}
export default PlacesModel;

View File

@ -0,0 +1,16 @@
import PlacesModel from "../../../common/model/placesModel";
import getPlacesRO from "../response-object/getPlacesRO";
import { GetPlacesResponse } from "../response-object/protocols";
const getPlacesRepo = async (httpHandler: () => Promise<GetPlacesResponse>) => {
// call httpHandler
const placesResponse = await httpHandler();
// user response object to turn it to the data that we want
const placesData = getPlacesRO(placesResponse);
// make model
const placesModel = new PlacesModel(placesData);
// return the model
return placesModel;
};
export default getPlacesRepo;

View File

@ -1,5 +1,5 @@
import { GetPlacesRO } from "../response-object/protocols";
import PlacesModel from "../../../common/model/placesModel";
type IGetPlacesRepo = () => Promise<GetPlacesRO>;
type IGetPlacesRepo = () => Promise<PlacesModel>;
export default IGetPlacesRepo;

View File

@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
import { GetPlacesRO, GetPlacesResponse } from "./protocols";
const getPlacesRO = (placeResponse: GetPlacesResponse): GetPlacesRO => ({
@ -8,6 +9,7 @@ const getPlacesRO = (placeResponse: GetPlacesResponse): GetPlacesRO => ({
availableServices: placeResponse.available_services,
createdAt: placeResponse.createdAt,
updatedAt: placeResponse.updatedAt,
})
qr: null,
});
export default getPlacesRO;

View File

@ -1,3 +1,5 @@
import Places from "../../../common/entity/placeEntity";
export type GetPlacesResponse = {
_id: string;
place_type: string;
@ -8,11 +10,7 @@ export type GetPlacesResponse = {
available_services: string[];
};
export type GetPlacesRO = {
id: string;
placeType: string;
name: string;
parentId: string | null;
export type GetPlacesRO = Places & {
availableServices: string[];
createdAt: string;
updatedAt: string;

View File

@ -0,0 +1,3 @@
import getPlaces from "./infra/getPlacesInfra";
export default getPlaces;

View File

@ -0,0 +1,18 @@
import PlacesModel from "../../common/model/placesModel";
import getPlacesRepo from "../data/repository/GetPlacesRepo";
import IGetPlacesRepo from "../data/repository/IGetPlacesRepo";
import GettingPlacesUsecase from "../usecase/getPlaceUsecase";
import { IgetPlacesInfra } from "./protocols";
const getPlaces = ({
httpHandler,
}: IgetPlacesInfra): (() => Promise<PlacesModel>) => {
// get httpHandler
const repository: IGetPlacesRepo = () => getPlacesRepo(httpHandler);
// connet usecase and repository
const usecase = new GettingPlacesUsecase(repository);
// return method to use
return () => usecase.execute();
};
export default getPlaces;

View File

@ -0,0 +1,5 @@
import { GetPlacesResponse } from "../data/response-object/protocols";
export interface IgetPlacesInfra {
httpHandler: () => Promise<GetPlacesResponse>;
}

View File

@ -0,0 +1,3 @@
import { type IgetPlacesInfra } from "./infra/protocols";
export default IgetPlacesInfra;

View File

@ -1,3 +1,4 @@
import PlacesModel from "../../../common/model/placesModel";
import IGetPlacesRepo from "../../data/repository/IGetPlacesRepo";
import { GetPlacesRO } from "../../data/response-object/protocols";
import GettingPlacesUsecase from "../getPlaceUsecase";
@ -10,10 +11,13 @@ const mockedRO: GetPlacesRO = {
parentId: null,
placeType: "continent",
updatedAt: "updatedTime",
qr: null,
};
const model = new PlacesModel(mockedRO);
const mockedRepo: IGetPlacesRepo = jest
.fn()
.mockImplementation(async () => mockedRO);
.mockImplementation(async () => model);
describe("getting places usecase tests", () => {
it("call repository on execute usecase", async () => {

View File

@ -1,5 +1,5 @@
import PlacesModel from "../../common/model/placesModel";
import IGetPlacesRepo from "../data/repository/IGetPlacesRepo";
import { GetPlacesRO } from "../data/response-object/protocols";
/**
* this usecase is responsible for calling the repo and returning the places data from the repository
@ -11,8 +11,10 @@ class GettingPlacesUsecase {
this.repository = repository;
}
async execute(): Promise<GetPlacesRO> {
async execute(): Promise<PlacesModel> {
// call usecase and return the repo
const placesData = await this.repository();
return placesData;
}
}

View File

@ -0,0 +1,30 @@
import { GetPlacesResponse } from "~/business-logic/core/places/get-places/data/response-object/protocols";
import IGetPlacesPort from "~/business-logic/core/places/get-places/port";
import { HTTPPovider } from "~/driven/boundaries/http-boundary/httpBoundary";
import { HttpOptionsType } from "~/driven/boundaries/http-boundary/protocols";
import { apiUrls } from "~/driven/utils/configs/appConfig";
const getPlacesAdapter = async (): Promise<IGetPlacesPort> => {
// url of api
const url = apiUrls.core.places;
// make the options of request
const options: HttpOptionsType = {
url,
method: "GET",
headers: {
"Content-Type": "application/json",
},
};
// make the httpHandler
const httpProvider = new HTTPPovider();
const httpHandler = async () =>
httpProvider.request<GetPlacesResponse>(options);
// return the method
return {
httpHandler,
};
};
export default getPlacesAdapter;

View File

@ -1,7 +1,8 @@
import axios, { AxiosRequestConfig } from "axios";
import { staticMessages } from "~/driven/utils/constants/staticMessages";
import { ApiGlobalResponseObject } from "~/driven/utils/protocols/serviceProtocols";
export class HTTPBoundary {
export class HTTPPovider {
async request<R>(customOptions: AxiosRequestConfig) {
const options: AxiosRequestConfig = {
...customOptions,
@ -10,9 +11,9 @@ export class HTTPBoundary {
Authorization: `Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4NXh0WnA5eThxVDBXVDkwUFpuUkRja3N4LWw0clVyM0tHQW5JSU9DckJNIn0.eyJleHAiOjE2ODQ1NzUyNDksImlhdCI6MTY4NDQ4ODg0OSwianRpIjoiYjI3MDUwMzYtMzMwZi00MTRkLWE2Y2QtNWRiYWUzOTRkMjczIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9kaXBhbF9kZXYiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiY2RmYzY3YzQtZGJkOC00NGVhLWI0OWEtYjQ3MjZhMzNmOTAxIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29tZm9ydGVjaCIsInNlc3Npb25fc3RhdGUiOiJmMzBhYzJlOS04ZTAxLTQxYjItYmI2OS0yYmMyNGEwOGRjNGUiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1tYXN0ZXIiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiY29tZm9ydGVjaCI6eyJyb2xlcyI6WyJ1c2VyIiwib3BlcmF0b3IiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImYzMGFjMmU5LThlMDEtNDFiMi1iYjY5LTJiYzI0YTA4ZGM0ZSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiKzc3Nzc3Nzc3Nzc3In0.tzM7W8szzcN1AK3XOtgUCGbHkmWd4bnqr-jvcwBICtNbl5Dty8RxK_ONFp6g5X8wI0pVPKx4qLvWkE7jXQcg1XDZW_H1V-ucZZ_a9POffDRZ5xSNcREnjfKhw3gvjK9YSSBeMf08abDexbVSJW4rbPxtmcO9WGdZN8C1k7O-_9VHz-3NBCq7vRYBNID--xVTga_MMv3mCORzHtUdx2D7B2d7YxBAjQs5x9JCl_eXuN_IHODc2HMww-s5akquzdEKGFSfASu30NpNZucbO9XyTMkAWuV-H9Xd73eq5o-tSd0jMOfY9G1it9xLAM2Gk4xmIuUA16aLnjY7_rmm3rOypw`,
},
};
const response = await axios<R>(options);
const response = await axios<ApiGlobalResponseObject<R>>(options);
if (!response) throw new Error(staticMessages.service.errors[500]);
return response.data;
return response.data.data;
}
}

View File

@ -0,0 +1,3 @@
import { AxiosRequestConfig } from "axios";
export type HttpOptionsType = AxiosRequestConfig;

View File

@ -1,4 +1,5 @@
import { icons } from "../constants/assertUrls";
import { ENVs } from "../constants/envs";
import { staticMessages } from "../constants/staticMessages";
export const appConfig = {};
@ -21,5 +22,9 @@ export const routesData = {
},
};
const baseApiUrl = import.meta.env.BASE_API_URL;
export const apiUrls = {};
const baseApiUrl = ENVs.apiOrigin;
export const apiUrls = {
core: {
places: `${baseApiUrl}${ENVs.apiPlaces}`,
},
};

View File

@ -0,0 +1,4 @@
export const ENVs = {
apiOrigin: process.env.VITE_API_ORIGIN,
apiPlaces: process.env.VITE_API_PLACES,
};

View File

@ -1,6 +1,6 @@
export type RequestMethods = "get" | "post" | "put" | "delete";
export type apiGlobalResponseObject<DataType> = {
export type ApiGlobalResponseObject<DataType> = {
type: "Success" | "client Error" | string;
status: 200 | 400 | 401 | 500 | number;
message: string;