Move disk data to a class

This commit is contained in:
powermaker450 2024-08-21 02:31:44 -04:00
parent fd4bc44842
commit 74c17bcd8e
4 changed files with 138 additions and 42 deletions

View file

@ -1,13 +1,15 @@
import { PostListener } from "./routes"; import { PostListener } from "./routes";
import express from "express"; import express from "express";
import dotenv from "dotenv"; import dotenv from "dotenv";
import { Logger } from "./utils"; import { checkFile, Logger } from "./utils";
import { ReviewData } from "./utils/ReviewData";
dotenv.config(); dotenv.config();
const app = express(); const app = express();
const post = new PostListener(app);
const logger = new Logger("Main"); 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; const port = +process.env.PORT || 8080;
post.start(); post.start();

View file

@ -1,19 +1,17 @@
import fs from "fs"; import fs from "fs";
import { import { ServerSideReview, userReviewSchema, typeJson } from "../types";
serverReviewSchema, import { bold, checkFile, emp, Logger, responder } from "../utils";
ServerSideReview,
userReviewSchema,
typeJson,
} from "../types";
import { appendId, bold, checkFile, emp, Logger, responder } from "../utils";
import { Express, Request, Response } from "express"; import { Express, Request, Response } from "express";
import { ReviewData } from "../utils/ReviewData";
export class PostListener { export class PostListener {
private server: Express; private server: Express;
private data: ReviewData;
private readonly logger = new Logger("Post Listener"); private readonly logger = new Logger("Post Listener");
constructor(server: Express) { constructor(server: Express, data: ReviewData) {
this.server = server; this.server = server;
this.data = data;
} }
public async start(): Promise<void> { public async start(): Promise<void> {
@ -44,22 +42,13 @@ export class PostListener {
req.on("end", () => { req.on("end", () => {
this.logger.log(`${sender} ~>`, validUserReview); this.logger.log(`${sender} ~>`, validUserReview);
serverReviewSchema try {
.validate(appendId(validUserReview)) this.data.appendReview(validUserReview);
.then((validServerReview) => {
data.push(validServerReview);
fs.writeFileSync(
"./persist/data.json",
JSON.stringify(data, null, 2),
);
res.writeHead(201, typeJson); res.writeHead(201, typeJson);
res.write(responder.success("review was sent")); res.write(responder.success("review was sent"));
res.end(); res.end();
}) } catch (err) {
.catch((err) => {
this.logger.error("Failed to assign ID to review:", err); this.logger.error("Failed to assign ID to review:", err);
res.writeHead(500, typeJson); res.writeHead(500, typeJson);
@ -67,7 +56,7 @@ export class PostListener {
responder.serverError("failed to assign ID to review"), responder.serverError("failed to assign ID to review"),
); );
res.end(); res.end();
}); }
}); });
}) })

View file

@ -1,10 +1,6 @@
import { object, string, number, InferType } from "yup"; import { object, string, number, InferType } from "yup";
export const typeJson = { "Content-Type": "application/json" }; const rating = number()
export const userReviewSchema = object({
username: string().min(2).max(30).required(),
rating: number()
.positive() .positive()
.max(5) .max(5)
.test( .test(
@ -12,7 +8,13 @@ export const userReviewSchema = object({
"Rating can only have at most one integer at half intervals (.0 or .5)", "Rating can only have at most one integer at half intervals (.0 or .5)",
(number) => (number! * 10) % 5 === 0, (number) => (number! * 10) % 5 === 0,
) )
.required(), .required();
export const typeJson = { "Content-Type": "application/json" };
export const userReviewSchema = object({
username: string().min(2).max(30).required(),
rating: rating,
title: string().max(50).notRequired(), title: string().max(50).notRequired(),
content: string().max(2000).notRequired(), content: string().max(2000).notRequired(),
}); });
@ -22,5 +24,5 @@ export const serverReviewSchema = userReviewSchema.shape({
}); });
export type UserSideReview = InferType<typeof userReviewSchema>; export type UserSideReview = InferType<typeof userReviewSchema>;
export type ServerSideReview = InferType<typeof serverReviewSchema>; export type ServerSideReview = InferType<typeof serverReviewSchema>;
export type userRating = InferType<typeof rating>;

103
src/utils/ReviewData.ts Normal file
View file

@ -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<void> {
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;
}
}