🦠 Added ignored folder back to git tracking
Signed-off-by: Rishi Ghan <rishi.ghan@gmail.com>
This commit is contained in:
18
src/server/README.md
Normal file
18
src/server/README.md
Normal file
@@ -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: <username>}` for requests to the URL (/api/test). It is also configured to serve the static files from **dist** directory.
|
||||||
29
src/server/index.ts
Normal file
29
src/server/index.ts
Normal file
@@ -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}`);
|
||||||
16
src/server/interfaces/folder.interface.ts
Normal file
16
src/server/interfaces/folder.interface.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export interface IFolderResponse {
|
||||||
|
data: Array<IFolderData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IComicVineSearchMatch {
|
||||||
|
description: string;
|
||||||
|
id: number;
|
||||||
|
volumes: string;
|
||||||
|
}
|
||||||
|
export interface IFolderData {
|
||||||
|
name: string;
|
||||||
|
extension: string;
|
||||||
|
containedIn: string;
|
||||||
|
isFile: boolean;
|
||||||
|
isLink: boolean;
|
||||||
|
}
|
||||||
7
src/server/interfaces/path.interface.ts
Normal file
7
src/server/interfaces/path.interface.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export interface IPathRoute {
|
||||||
|
methods: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Ipath {
|
||||||
|
[route: string]: IPathRoute;
|
||||||
|
}
|
||||||
1
src/server/route/README.md
Normal file
1
src/server/route/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
## Read me for routes
|
||||||
3
src/server/route/index.ts
Normal file
3
src/server/route/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import extra from "./routes/importComics.routes";
|
||||||
|
|
||||||
|
export default { extra };
|
||||||
12
src/server/route/path.ts
Normal file
12
src/server/route/path.ts
Normal file
@@ -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;
|
||||||
5
src/server/route/router.ts
Normal file
5
src/server/route/router.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import express, { Router } from "express";
|
||||||
|
|
||||||
|
const router: Router = express.Router();
|
||||||
|
|
||||||
|
export default router;
|
||||||
16
src/server/route/routes/importComics.routes.ts
Normal file
16
src/server/route/routes/importComics.routes.ts
Normal file
@@ -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;
|
||||||
73
src/server/utils/fs.utils.ts
Normal file
73
src/server/utils/fs.utils.ts
Normal file
@@ -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);
|
||||||
|
});
|
||||||
|
};
|
||||||
20
src/server/utils/logger.utils.ts
Normal file
20
src/server/utils/logger.utils.ts
Normal file
@@ -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,
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user