From 74c17bcd8e38e5eafaf41c2b182832e65f8571d4 Mon Sep 17 00:00:00 2001 From: powermaker450 Date: Wed, 21 Aug 2024 02:31:44 -0400 Subject: [PATCH] Move disk data to a class --- src/main.ts | 6 ++- src/routes/post.ts | 49 ++++++++----------- src/types.ts | 22 +++++---- src/utils/ReviewData.ts | 103 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 42 deletions(-) create mode 100644 src/utils/ReviewData.ts diff --git a/src/main.ts b/src/main.ts index 37885ea..449bec1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,13 +1,15 @@ import { PostListener } from "./routes"; import express from "express"; import dotenv from "dotenv"; -import { Logger } from "./utils"; +import { checkFile, Logger } from "./utils"; +import { ReviewData } from "./utils/ReviewData"; dotenv.config(); const app = express(); -const post = new PostListener(app); const logger = new Logger("Main"); +const data = new ReviewData(checkFile("data.json", "utf8")); +const post = new PostListener(app, data); const port = +process.env.PORT || 8080; post.start(); diff --git a/src/routes/post.ts b/src/routes/post.ts index 3d053db..affb9f7 100644 --- a/src/routes/post.ts +++ b/src/routes/post.ts @@ -1,19 +1,17 @@ import fs from "fs"; -import { - serverReviewSchema, - ServerSideReview, - userReviewSchema, - typeJson, -} from "../types"; -import { appendId, bold, checkFile, emp, Logger, responder } from "../utils"; +import { ServerSideReview, userReviewSchema, typeJson } from "../types"; +import { bold, checkFile, emp, Logger, responder } from "../utils"; import { Express, Request, Response } from "express"; +import { ReviewData } from "../utils/ReviewData"; export class PostListener { private server: Express; + private data: ReviewData; private readonly logger = new Logger("Post Listener"); - constructor(server: Express) { + constructor(server: Express, data: ReviewData) { this.server = server; + this.data = data; } public async start(): Promise { @@ -44,30 +42,21 @@ export class PostListener { req.on("end", () => { this.logger.log(`${sender} ~>`, validUserReview); - serverReviewSchema - .validate(appendId(validUserReview)) + try { + this.data.appendReview(validUserReview); - .then((validServerReview) => { - data.push(validServerReview); - fs.writeFileSync( - "./persist/data.json", - JSON.stringify(data, null, 2), - ); + res.writeHead(201, typeJson); + res.write(responder.success("review was sent")); + res.end(); + } catch (err) { + this.logger.error("Failed to assign ID to review:", err); - res.writeHead(201, typeJson); - res.write(responder.success("review was sent")); - res.end(); - }) - - .catch((err) => { - this.logger.error("Failed to assign ID to review:", err); - - res.writeHead(500, typeJson); - res.write( - responder.serverError("failed to assign ID to review"), - ); - res.end(); - }); + res.writeHead(500, typeJson); + res.write( + responder.serverError("failed to assign ID to review"), + ); + res.end(); + } }); }) diff --git a/src/types.ts b/src/types.ts index 11ccaeb..f5ed585 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,18 +1,20 @@ import { object, string, number, InferType } from "yup"; +const rating = number() + .positive() + .max(5) + .test( + "maxDigitsAfterDecimal", + "Rating can only have at most one integer at half intervals (.0 or .5)", + (number) => (number! * 10) % 5 === 0, + ) + .required(); + export const typeJson = { "Content-Type": "application/json" }; export const userReviewSchema = object({ username: string().min(2).max(30).required(), - rating: number() - .positive() - .max(5) - .test( - "maxDigitsAfterDecimal", - "Rating can only have at most one integer at half intervals (.0 or .5)", - (number) => (number! * 10) % 5 === 0, - ) - .required(), + rating: rating, title: string().max(50).notRequired(), content: string().max(2000).notRequired(), }); @@ -22,5 +24,5 @@ export const serverReviewSchema = userReviewSchema.shape({ }); export type UserSideReview = InferType; - export type ServerSideReview = InferType; +export type userRating = InferType; diff --git a/src/utils/ReviewData.ts b/src/utils/ReviewData.ts new file mode 100644 index 0000000..13939b1 --- /dev/null +++ b/src/utils/ReviewData.ts @@ -0,0 +1,103 @@ +import fs from "fs"; +import { + serverReviewSchema, + ServerSideReview, + userRating, + UserSideReview, +} from "../types"; +import { appendId } from "./functions"; + +export class ReviewData { + public data: ServerSideReview[]; + + constructor(existingData?: ServerSideReview[]) { + this.data = existingData ?? []; + } + + public async appendReview(review: UserSideReview): Promise { + await serverReviewSchema + .validate(appendId(review)) + + .then((validReview) => { + this.data.push(validReview); + fs.writeFileSync( + "./persist/data.json", + JSON.stringify(this.data, null, 2), + ); + }) + + .catch((err) => { + throw new err(); + }); + } + + public getReviews(maxCount = Infinity): ServerSideReview[] { + let final: ServerSideReview[] = []; + + while (final.length < maxCount) { + for (const review of this.data) { + final.push(review); + } + } + + return final; + } + + public getReviewById(id: string): ServerSideReview | {} { + for (const review of this.data) { + if (review.id === id) { + return review; + } + } + + return {}; + } + + public getReviewsByUsername( + username: string, + maxCount = Infinity, + ): ServerSideReview[] { + let final: ServerSideReview[] = []; + + while (final.length < maxCount) { + for (const review of this.data) { + if (review.username === username) { + final.push(review); + } + } + } + + return final; + } + + public getReviewsByRating( + rating: userRating, + maxCount = Infinity, + ): ServerSideReview[] { + let final: ServerSideReview[] = []; + + while (final.length < maxCount) { + for (const review of this.data) { + if (review.rating === rating) { + final.push(review); + } + } + } + + return final; + } + + public getEmptyReviews(maxCount = Infinity): ServerSideReview[] { + let final: ServerSideReview[] = []; + + while (final.length < maxCount) { + for (const review of this.data) { + if (!review.content && !review.title) { + final.push(review); + } + } + } + + return final; + } +}