From 22a5cba98d1d479aab20ac1918c4aa41342b8df1 Mon Sep 17 00:00:00 2001 From: Rishi Ghan Date: Thu, 15 Apr 2021 15:15:23 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=A0=20Added=20ignored=20folder=20back?= =?UTF-8?q?=20to=20git=20tracking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rishi Ghan --- src/server/README.md | 18 +++++ src/server/index.ts | 29 ++++++++ src/server/interfaces/folder.interface.ts | 16 ++++ src/server/interfaces/path.interface.ts | 7 ++ src/server/route/README.md | 1 + src/server/route/index.ts | 3 + src/server/route/path.ts | 12 +++ src/server/route/router.ts | 5 ++ .../route/routes/importComics.routes.ts | 16 ++++ src/server/utils/fs.utils.ts | 73 +++++++++++++++++++ src/server/utils/logger.utils.ts | 20 +++++ 11 files changed, 200 insertions(+) create mode 100644 src/server/README.md create mode 100644 src/server/index.ts create mode 100644 src/server/interfaces/folder.interface.ts create mode 100644 src/server/interfaces/path.interface.ts create mode 100644 src/server/route/README.md create mode 100644 src/server/route/index.ts create mode 100644 src/server/route/path.ts create mode 100644 src/server/route/router.ts create mode 100644 src/server/route/routes/importComics.routes.ts create mode 100644 src/server/utils/fs.utils.ts create mode 100644 src/server/utils/logger.utils.ts diff --git a/src/server/README.md b/src/server/README.md new file mode 100644 index 0000000..96d5a96 --- /dev/null +++ b/src/server/README.md @@ -0,0 +1,18 @@ +# Server side boilerplate with MongoDB as database, Express framework with Typescript + +## Introduction + +In the Server side of boilerplate, MongoDB and Express framework with Typescript has been utilized to reach a well structured and fully separated concerns source code. +the source code has been separated into multiple layers and every layer fully explaind with lots of details in their own README files. + + +### Nodemon + +Nodemon is a utility monitors for any changes in the server-side source code, and automatically restarts the server. Nodemon is just for development purposes only. +**nodemon.json** file is used to hold the configurations for Nodemon. + +### Express + +Express is a web application framework for Node.js. It is used to build our backend API's. + +**src/server/index.ts** is the entry point to the server application which starts a server and listens on port 8085 for connections. The app responds with `{username: }` for requests to the URL (/api/test). It is also configured to serve the static files from **dist** directory. diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 0000000..dc36b90 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,29 @@ +import express, { Request, Response, Router, Express } from "express"; +import bodyParser from "body-parser"; +import router from "./route"; + +// call express +const app: Express = express(); // define our app using express + +// configure app to use bodyParser for +// Getting data from body of requests +app.use(bodyParser.json()); + +app.use(bodyParser.urlencoded({ extended: true })); + +const port: number = Number(process.env.PORT) || 8050; // set our port + +// Send index.html on root request +app.use(express.static("dist")); +app.get("/", (req: Request, res: Response) => { + console.log("sending index.html"); + res.sendFile("/dist/index.html"); +}); + +// REGISTER ROUTES +// all of the routes will be prefixed with /api +const routes: Router[] = Object.values(router); +app.use("/api", routes); + +app.listen(port); +console.log(`App listening on ${port}`); diff --git a/src/server/interfaces/folder.interface.ts b/src/server/interfaces/folder.interface.ts new file mode 100644 index 0000000..1db74c8 --- /dev/null +++ b/src/server/interfaces/folder.interface.ts @@ -0,0 +1,16 @@ +export interface IFolderResponse { + data: Array; +} + +export interface IComicVineSearchMatch { + description: string; + id: number; + volumes: string; +} +export interface IFolderData { + name: string; + extension: string; + containedIn: string; + isFile: boolean; + isLink: boolean; +} diff --git a/src/server/interfaces/path.interface.ts b/src/server/interfaces/path.interface.ts new file mode 100644 index 0000000..dcc5f87 --- /dev/null +++ b/src/server/interfaces/path.interface.ts @@ -0,0 +1,7 @@ +export interface IPathRoute { + methods: string[]; +} + +export interface Ipath { + [route: string]: IPathRoute; +} diff --git a/src/server/route/README.md b/src/server/route/README.md new file mode 100644 index 0000000..03f67ff --- /dev/null +++ b/src/server/route/README.md @@ -0,0 +1 @@ +## Read me for routes \ No newline at end of file diff --git a/src/server/route/index.ts b/src/server/route/index.ts new file mode 100644 index 0000000..5c0245e --- /dev/null +++ b/src/server/route/index.ts @@ -0,0 +1,3 @@ +import extra from "./routes/importComics.routes"; + +export default { extra }; diff --git a/src/server/route/path.ts b/src/server/route/path.ts new file mode 100644 index 0000000..4c43de8 --- /dev/null +++ b/src/server/route/path.ts @@ -0,0 +1,12 @@ +import { Ipath, IPathRoute } from "../interfaces/path.interface"; + +function path(url: string): IPathRoute { + const allRoutes: Ipath = { + "/extra": { + methods: ["POST", "GET", "PUT"], + }, + }; + return allRoutes[url]; +} + +export default path; diff --git a/src/server/route/router.ts b/src/server/route/router.ts new file mode 100644 index 0000000..3f3c906 --- /dev/null +++ b/src/server/route/router.ts @@ -0,0 +1,5 @@ +import express, { Router } from "express"; + +const router: Router = express.Router(); + +export default router; diff --git a/src/server/route/routes/importComics.routes.ts b/src/server/route/routes/importComics.routes.ts new file mode 100644 index 0000000..931f0f7 --- /dev/null +++ b/src/server/route/routes/importComics.routes.ts @@ -0,0 +1,16 @@ +import router from "../router"; +import { walkFolder, extractArchive } from "../../utils/fs.utils"; +import { Request, Response } from "express"; + +router.route("/getComicCovers").get((req: Request, res: Response) => { + res.json({ + jagan: "trupti", + }); +}); + +router.route("/walkFolder").get(async (req: Request, res: Response) => { + const results = await walkFolder(req.params.basePathToWalk); + res.json(results); +}); + +export default router; diff --git a/src/server/utils/fs.utils.ts b/src/server/utils/fs.utils.ts new file mode 100644 index 0000000..ca576b7 --- /dev/null +++ b/src/server/utils/fs.utils.ts @@ -0,0 +1,73 @@ +import unrarer from "node-unrar-js"; +import { default as unzipper } from "unzipper"; +const etl = require("etl"); +const Walk = require("@root/walk"); +import fs from "fs"; +import path from "path"; +import { logger } from "./logger.utils"; +import { IFolderData } from "../interfaces/folder.interface"; + +export const unrar = async (filePath) => { + const buf = Uint8Array.from( + fs.readFileSync("./comics/The Squidder (2015) (Digital-Empire).cbr"), + ).buffer; + const extractor = await unrarer.createExtractorFromData({ data: buf }); + const list = extractor.getFileList(); + const fileHeaders = [...list.fileHeaders]; + const extracted = extractor.extract({ files: [fileHeaders[0].name] }); + const files = [...extracted.files]; //load the files + return files[0]; +}; + +export const unzip = () => { + fs.createReadStream("./comics/30 Days of Night 01-003.cbz") + .pipe(unzipper.ParseOne()) + .pipe(etl.toFile("./comics/covers/cover.jpg")) + .promise() + .then(() => { + logger.info("done"); + }) + .catch((e) => { + logger.info("error", e); + }); +}; + +export const extractArchive = async (pathName) => { + const extractedFile = await unrar("./comics"); + const myBuffer = extractedFile.extraction; + logger.info(`Attempting to write ${extractedFile.fileHeader.name}`); + fs.writeFile(pathName + extractedFile.fileHeader.name, myBuffer, (err) => { + if (err) { + logger.error("Failed to write file", err); + } else { + logger.info( + `The file ${extractedFile.fileHeader.name} was saved to disk.`, + ); + } + }); +}; + +export const walkFolder = async (folder: string): Promise<[IFolderData]> => { + const result: IFolderData[] = []; + return await Walk.walk(folder, async (err, pathname, dirent) => { + // err is failure to lstat a file or directory + // pathname is relative path, including the file or folder name + // dirent = { name, isDirectory(), isFile(), isSymbolicLink(), ... } + + if (err) { + logger.error("Failed to lstat directory", { error: err }); + return false; + } + const walkResult = { + name: path.basename(dirent.name, path.extname(dirent.name)), + extension: path.extname(dirent.name), + containedIn: path.dirname(pathname), + isFile: dirent.isFile(), + isLink: dirent.isSymbolicLink(), + }; + logger.info( + `Scanned ${dirent.name} contained in ${path.dirname(pathname)}`, + ); + result.push(walkResult); + }); +}; diff --git a/src/server/utils/logger.utils.ts b/src/server/utils/logger.utils.ts new file mode 100644 index 0000000..d47c965 --- /dev/null +++ b/src/server/utils/logger.utils.ts @@ -0,0 +1,20 @@ +import { default as Pino } from "pino"; +import { default as pinopretty } from "pino-pretty"; + +export const logger = Pino({ + name: "threetwo!", + prettyPrint: { colorize: true }, + // crlf: false, + // errorLikeObjectKeys: ["err", "error"], + // errorProps: "", + // levelFirst: false, // --levelFirst + messageKey: "msg", // --messageKey + levelKey: "level", // --levelKey + // messageFormat: false, // --messageFormat + // timestampKey: "time", // --timestampKey + // translateTime: false, // --translateTime + // search: "foo == `bar`", // --search + // ignore: "pid,hostname", // --ignore + // hideObject: false, // --hideObject + // singleLine: false, +});