Skip to content

Commit

Permalink
Added behaviour endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
DanZfsd committed Jun 22, 2024
1 parent 88bfc66 commit eef616c
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 2 deletions.
20 changes: 20 additions & 0 deletions backend/typescript/middlewares/validators/behaviourValidators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Request, Response, NextFunction } from "express";
import {
getApiValidationError,
validateArray,

Check warning on line 4 in backend/typescript/middlewares/validators/behaviourValidators.ts

View workflow job for this annotation

GitHub Actions / run-lint

'validateArray' is defined but never used
validatePrimitive,
} from "./util";

/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable-next-line import/prefer-default-export */
export const behaviourRequestDtoValidators = async (
req: Request,
res: Response,
next: NextFunction,
) => {
const { body } = req;
if (!validatePrimitive(body.behaviourName, "string")) {
return res.status(400).send(getApiValidationError("behaviourName", "string"));

Check failure on line 17 in backend/typescript/middlewares/validators/behaviourValidators.ts

View workflow job for this annotation

GitHub Actions / run-lint

Replace `.status(400)` with `⏎······.status(400)⏎······`
}
return next();
};
2 changes: 1 addition & 1 deletion backend/typescript/models/behaviour.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Column, Model, Table } from "sequelize-typescript";

@Table({ tableName: "behaviours" })
@Table({ timestamps: false, tableName: "behaviours" })
export default class Behaviour extends Model {
@Column
behaviour_name!: string;
Expand Down
95 changes: 95 additions & 0 deletions backend/typescript/rest/behaviourRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Router } from "express";
import { isAuthorizedByRole } from "../middlewares/auth";

Check warning on line 2 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

'isAuthorizedByRole' is defined but never used
import { behaviourRequestDtoValidators } from "../middlewares/validators/behaviourValidators";
import BehaviourService from "../services/implementations/behaviourService";
import {
BehaviourResponseDTO,
IBehaviourService,
} from "../services/interfaces/behaviourService";
import { getErrorMessage } from "../utilities/errorUtils";
import { sendResponseByMimeType } from "../utilities/responseUtil";

const behaviourRouter: Router = Router();

Check failure on line 12 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `·`

const behaviourService: IBehaviourService = new BehaviourService();

/* Create Behaviour */
behaviourRouter.post(

Check failure on line 17 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Replace `⏎··"/",⏎··behaviourRequestDtoValidators,⏎·` with `"/",·behaviourRequestDtoValidators,`
"/",
behaviourRequestDtoValidators,
async (req, res) => {
try {

Check failure on line 21 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
const { body } = req;

Check failure on line 22 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
const newBehaviour = await behaviourService.createBehaviour({

Check failure on line 23 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
behaviourName: body.behaviourName,

Check failure on line 24 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Replace `········behaviourName:·body.behaviourName,·` with `······behaviourName:·body.behaviourName,`
});

Check failure on line 25 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
res.status(201).json(newBehaviour);

Check failure on line 26 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
} catch (e: unknown) {

Check failure on line 27 in backend/typescript/rest/behaviourRoutes.ts

View workflow job for this annotation

GitHub Actions / run-lint

Delete `··`
res.status(500).send(getErrorMessage(e));
}
},
);

/* Get all Behaviours */
behaviourRouter.get("/", async (req, res) => {
const contentType = req.headers["content-type"];
try {
const behaviours = await behaviourService.getBehaviours();
await sendResponseByMimeType<BehaviourResponseDTO>(
res,
200,
contentType,
behaviours,
);
} catch (e: unknown) {
await sendResponseByMimeType(res, 500, contentType, [
{
error: getErrorMessage(e),
},
]);
}
});

/* Get Behaviour by id */
behaviourRouter.get("/:id", async (req, res) => {
const { id } = req.params;

try {
const behaviour = await behaviourService.getBehaviour(id);
res.status(200).json(behaviour);
} catch (e: unknown) {
res.status(500).send(getErrorMessage(e));
}
});

/* Update Behaviour by id */
behaviourRouter.put(
"/:id",
behaviourRequestDtoValidators,
async (req, res) => {
const { id } = req.params;
try {
const { body } = req;
const behaviour = await behaviourService.updateBehaviour(id, {
behaviourName: body.behaviourName,
});
res.status(200).json(behaviour);
} catch (e: unknown) {
res.status(500).send(getErrorMessage(e));
}
},
);

/* Delete Behaviour by id */
behaviourRouter.delete("/:id", async (req, res) => {
const { id } = req.params;

try {
const deletedId = await behaviourService.deleteBehaviour(id);
res.status(200).json({ id: deletedId });
} catch (e: unknown) {
res.status(500).send(getErrorMessage(e));
}
});

export default behaviourRouter;
4 changes: 3 additions & 1 deletion backend/typescript/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import YAML from "yamljs";

import { sequelize } from "./models";
import authRouter from "./rest/authRoutes";
import behaviourRouter from "./rest/behaviourRoutes";
import entityRouter from "./rest/entityRoutes";
import simpleEntityRouter from "./rest/simpleEntityRoutes";
import userRouter from "./rest/userRoutes";
import userRouter from "./rest/userRoutes";

const CORS_ALLOW_LIST = [
"http://localhost:3000",
Expand All @@ -32,6 +33,7 @@ app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use("/auth", authRouter);
app.use("/behaviours", behaviourRouter);
app.use("/entities", entityRouter);
app.use("/simple-entities", simpleEntityRouter);
app.use("/users", userRouter);
Expand Down
117 changes: 117 additions & 0 deletions backend/typescript/services/implementations/behaviourService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import PgBehaviour from "../../models/behaviour.model";
import {
IBehaviourService,
BehaviourRequestDTO,
BehaviourResponseDTO,
} from "../interfaces/behaviourService";
import { getErrorMessage } from "../../utilities/errorUtils";
import logger from "../../utilities/logger";

const Logger = logger(__filename);

class BehaviourService implements IBehaviourService {
/* eslint-disable class-methods-use-this */
async getBehaviour(id: string): Promise<BehaviourResponseDTO> {
let behaviour: PgBehaviour | null;
try {
behaviour = await PgBehaviour.findByPk(id, { raw: true });
if (!behaviour) {
throw new Error(`Behaviour id ${id} not found`);
}
} catch (error: unknown) {
Logger.error(`Failed to get behaviour. Reason = ${getErrorMessage(error)}`);
throw error;
}

return {
id: String(behaviour.id),
behaviourName: behaviour.behaviour_name,
};
}

async getBehaviours(): Promise<BehaviourResponseDTO[]> {
try {
const behaviours: Array<PgBehaviour> = await PgBehaviour.findAll({
raw: true,
});
return behaviours.map((behaviour) => ({
id: String(behaviour.id),
behaviourName: behaviour.behaviour_name,
}));
} catch (error: unknown) {
Logger.error(
`Failed to get behaviours. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
}

async createBehaviour(
behaviour: BehaviourRequestDTO,
): Promise<BehaviourResponseDTO> {
let newBehaviour: PgBehaviour | null;
try {
newBehaviour = await PgBehaviour.create({
behaviour_name: behaviour.behaviourName,
});
} catch (error: unknown) {
Logger.error(
`Failed to create behaviour. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
return {
id: String(newBehaviour.id),
behaviourName: newBehaviour?.behaviour_name,
};
}

async updateBehaviour(
id: string,
behaviour: BehaviourRequestDTO,
): Promise<BehaviourResponseDTO | null> {
let resultingBehaviour: PgBehaviour | null;
let updateResult: [number, PgBehaviour[]] | null;
try {
updateResult = await PgBehaviour.update(
{
behaviour_name: behaviour.behaviourName,
},
{ where: { id }, returning: true },
);

if (!updateResult[0]) {
throw new Error(`Behaviour id ${id} not found`);
}
[, [resultingBehaviour]] = updateResult;
} catch (error: unknown) {
Logger.error(
`Failed to update behaviour. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
return {
id: String(resultingBehaviour.id),
behaviourName: resultingBehaviour?.behaviour_name,
};
}

async deleteBehaviour(id: string): Promise<string> {
try {
const deleteResult: number | null = await PgBehaviour.destroy({
where: { id },
});
if (!deleteResult) {
throw new Error(`Behaviour id ${id} not found`);
}
return id;
} catch (error: unknown) {
Logger.error(
`Failed to delete behaviour. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
}
}

export default BehaviourService;
57 changes: 57 additions & 0 deletions backend/typescript/services/interfaces/behaviourService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export interface BehaviourRequestDTO {
behaviourName: string;
}

export interface BehaviourResponseDTO {
id: string;
behaviourName: string;
}

export interface IBehaviourService {
/**
* retrieve the Behaviour with the given id
* @param id Behaviour id
* @returns requested Behaviour
* @throws Error if retrieval fails
*/
getBehaviour(id: string): Promise<BehaviourResponseDTO>;

/**
* retrieve all Behaviours
* @param
* @returns returns array of Behaviours
* @throws Error if retrieval fails
*/
getBehaviours(): Promise<BehaviourResponseDTO[]>;

/**
* create a Behaviour with the fields given in the DTO, return created Behaviour
* @param behaviour new Behaviour
* @returns the created Behaviour
* @throws Error if creation fails
*/
createBehaviour(
behaviour: BehaviourRequestDTO,
): Promise<BehaviourResponseDTO>;

/**
* update the Behaviour with the given id with fields in the DTO, return updated Behaviour
* @param id Behaviour id
* @param behaviour Updated Behaviour
* @returns the updated Behaviour
* @throws Error if update fails
*/
updateBehaviour(
id: string,
behaviour: BehaviourRequestDTO,
): Promise<BehaviourResponseDTO | null>;

/**
* delete the Behaviour with the given id
* @param id Behaviour id
* @returns id of the Behaviour deleted
* @throws Error if deletion fails
*/
deleteBehaviour(id: string): Promise<string>;
}

0 comments on commit eef616c

Please sign in to comment.