page2pdf_server 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/package.json +4 -69
- package/src/index.ts +11 -18
- package/tsconfig.json +3 -3
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -28
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -15
- package/.github/ISSUE_TEMPLATE/refactoring.md +0 -15
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -18
- package/.github/stale.yml +0 -17
- package/.github/workflows/cd.yml +0 -75
- package/.github/workflows/ci.yml +0 -36
- package/.prettierrc +0 -8
- package/.vscode/settings.json +0 -3
- package/config/default.json +0 -10
- package/config/development.json +0 -3
- package/config/production.json +0 -3
- package/config/test.json +0 -3
- package/ecosystem.config.js +0 -41
- package/jest.config.js +0 -35
- package/nodemon.json +0 -6
- package/src/CSS/345/205/274/345/256/271/346/200/247.txt +0 -125
- package/src/__tests__/UrltoPdf/generatePdf.test.d.ts +0 -1
- package/src/__tests__/UrltoPdf/generatePdf.test.ts +0 -207
- package/src/__tests__/UrltoPdf/pdfSplit.test.d.ts +0 -1
- package/src/__tests__/UrltoPdf/pdfSplit.test.ts +0 -69
- package/src/__tests__/helpers/index.d.ts +0 -2
- package/src/__tests__/helpers/index.ts +0 -21
- package/src/__tests__/home.test.d.ts +0 -1
- package/src/__tests__/home.test.ts +0 -77
- package/src/app.ts +0 -49
- package/src/components/home/controller.ts +0 -32
- package/src/components/home/index.ts +0 -4
- package/src/components/home/pdfController.ts +0 -113
- package/src/components/home/services.ts +0 -31
- package/src/components/home/splitController.ts +0 -125
- package/src/components/home/validators.ts +0 -12
- package/src/configEnv/index.ts +0 -62
- package/src/db/home.ts +0 -14
- package/src/helpers/apiResponse.ts +0 -10
- package/src/helpers/dataSanitizers.ts +0 -32
- package/src/helpers/error/ApiError.ts +0 -25
- package/src/helpers/error/ForbiddenError.ts +0 -15
- package/src/helpers/error/NotFoundException.ts +0 -15
- package/src/helpers/error/TimeOutError.ts +0 -20
- package/src/helpers/error/UnauthorizedError.ts +0 -15
- package/src/helpers/error/ValidationError.ts +0 -20
- package/src/helpers/error/index.ts +0 -15
- package/src/helpers/index.ts +0 -2
- package/src/helpers/loggers.ts +0 -75
- package/src/middlewares/errorHandler.ts +0 -52
- package/src/new_tab1.mhtml +0 -722
- package/src/routes/index.ts +0 -22
- package/src/server.ts +0 -30
- package/src/testCSS.html +0 -241
- package/src/types/global.d.ts +0 -13
- package/src/types/request/home.ts +0 -3
- package/src/types/request/split.ts +0 -18
- package/src/types/response/AppInformation.ts +0 -9
- package/src/types/response/index.ts +0 -5
- package/src/utils/array.ts +0 -19
- package/src/utils/auth.ts +0 -12
- package/src/utils/crypt.ts +0 -25
- package/src/utils/filter.ts +0 -59
- package/src/utils/object.ts +0 -58
- package/src/utils/pdfgen.ts +0 -1045
- package/src/utils/url.ts +0 -54
- package/src//346/265/213/350/257/225.txt +0 -268
- package/test//346/211/223/345/215/260/346/234/215/345/212/241.http +0 -17
- package//346/226/207/344/271/246/346/211/223/345/215/260/350/275/254/346/215/242/345/231/250.bat +0 -2
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import { OK } from "http-status/lib";
|
|
3
|
-
import { HeadFooter } from "../../types/request/config";
|
|
4
|
-
import { apiResponse } from "../../helpers/apiResponse";
|
|
5
|
-
|
|
6
|
-
import { RenderPDF } from "../../utils/pdfgen";
|
|
7
|
-
import CONFIG from "../../configEnv";
|
|
8
|
-
import { SplitConfig, SplitPdfFile } from "../../types/request/split";
|
|
9
|
-
import { ConfigRoot, FileTransform } from "@/types";
|
|
10
|
-
// import CONFIG from "@/configEnv";
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12
|
-
const { PDFDocument } = require("pdf-lib");
|
|
13
|
-
|
|
14
|
-
/**只好拆分多个文件:就为了能够jest运行于单步调试模式啊。
|
|
15
|
-
* __test__/./generatePdf.test.ts问题:jest用Run模式正常,可是若Debug模式单步调试的,.post(`/api/pdf`).send就会提前中止!原因xxxController容不下多个接口函数?
|
|
16
|
-
* ?估计同一个.ts文件引入的包有动态编译的问题?非得拆分两个文件。
|
|
17
|
-
* */
|
|
18
|
-
export class SplitController {
|
|
19
|
-
/** node.js对比前端App 太严格了,一点小毛病页不行啊。
|
|
20
|
-
* @description 生成pdf.
|
|
21
|
-
* @param {Req} req
|
|
22
|
-
* @param {Res} res
|
|
23
|
-
* 正常分解成两大步:task.files每一个文件生成,最后才是task.merge合并(包括页码生成)。
|
|
24
|
-
* @param next
|
|
25
|
-
*/
|
|
26
|
-
//仅仅测试的
|
|
27
|
-
static postMakePdf = async (req: Req, res: Res, next: NextFn) => {
|
|
28
|
-
try {
|
|
29
|
-
// const appInfoKey1 = req.query.key as getAppInfoQuery;
|
|
30
|
-
const task = req.body as ConfigRoot<FileTransform>;
|
|
31
|
-
task.lay as HeadFooter;
|
|
32
|
-
//预处理汇总输出的pdf页眉页脚
|
|
33
|
-
if (task.lay) {
|
|
34
|
-
const newfoot = "";
|
|
35
|
-
const formfoot =
|
|
36
|
-
task.lay.foot &&
|
|
37
|
-
newfoot.concat(...task.lay.foot).replaceAll(`\\"`, '"');
|
|
38
|
-
task.footerTemplate = formfoot ?? undefined;
|
|
39
|
-
const formhead =
|
|
40
|
-
task.lay.head &&
|
|
41
|
-
newfoot.concat(...task.lay.head).replaceAll(`\\"`, '"');
|
|
42
|
-
task.headerTemplate = formhead ?? undefined;
|
|
43
|
-
}
|
|
44
|
-
//const homeServices = new HomeServices();
|
|
45
|
-
//let result = { ["文件名"]: "产生的.pdf" };
|
|
46
|
-
let result;
|
|
47
|
-
//若是用RenderPDF.generateSinglePdf(会导致没有等待该函数执行结果就会去执行下一步了,应答res,客户端立刻获得http回答,无等待=异步模式的。还是由客户端主动取消等待为佳。这里死等的;
|
|
48
|
-
try {
|
|
49
|
-
//const jobs = generateJobList(urls, pdfs); 分解成多个URL文件多个步骤的情况,可能还有个汇总步骤的:
|
|
50
|
-
// generateSinglePdf mergePdfs pageNoForPdf yeMeiyeJiaoPdf
|
|
51
|
-
if (
|
|
52
|
-
(task.merge === undefined || task.merge) &&
|
|
53
|
-
task.files === undefined &&
|
|
54
|
-
!task.lay
|
|
55
|
-
) {
|
|
56
|
-
await RenderPDF.mergeAllPdfto(); //特殊的特殊?
|
|
57
|
-
result = `简易合并输出是: ${CONFIG.APP.MERGE}`;
|
|
58
|
-
} else {
|
|
59
|
-
//正常的合并阶段的事情: 前一阶段页眉页脚也不打印了。也要放这里了
|
|
60
|
-
//if(task.merge===undefined || task.merge)
|
|
61
|
-
result = await RenderPDF.MergeAllPdfs(task, {});
|
|
62
|
-
}
|
|
63
|
-
} catch (e) {
|
|
64
|
-
result = "算失败了" + e;
|
|
65
|
-
console.error(e);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!result || result === "") result = "成功!";
|
|
69
|
-
res.status(OK).json(apiResponse({ result: result }));
|
|
70
|
-
} catch (error) {
|
|
71
|
-
next(error);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**拆分需要:支持pdf源文件的,抽取部分纸张页生成新文件*/
|
|
76
|
-
static postSplitPdf = async (req: Req, res: Res, next: NextFn) => {
|
|
77
|
-
try {
|
|
78
|
-
//也可能?用CDP:printPDF()来进行部分打印的后保存,就等于拆分pdf;
|
|
79
|
-
const task = req.body as SplitConfig;
|
|
80
|
-
task.files as SplitPdfFile[];
|
|
81
|
-
//输入文件 都是pdf了
|
|
82
|
-
const srcDoc = await PDFDocument.load(
|
|
83
|
-
fs.readFileSync(CONFIG.APP.PATH + "/" + task.input),
|
|
84
|
-
);
|
|
85
|
-
let result;
|
|
86
|
-
const allpagesum = await srcDoc.getPages().length;
|
|
87
|
-
//若是用RenderPDF.generateSinglePdf(会导致没有等待该函数执行结果就会去执行下一步了,应答res,客户端立刻获得http回答,无等待=异步模式的。还是由客户端主动取消等待为佳。这里死等的;
|
|
88
|
-
try {
|
|
89
|
-
for (const fileone of task.files) {
|
|
90
|
-
const oneDoc = await PDFDocument.create();
|
|
91
|
-
//可能出现例子是 '1-5, 8, 11-13' 类似打印机常见的选择页码范围。
|
|
92
|
-
const ofstr = fileone.pageRanges;
|
|
93
|
-
const ranges = ofstr.split(",");
|
|
94
|
-
for (const range of ranges) {
|
|
95
|
-
const bgend = range.split("-");
|
|
96
|
-
const beginp = bgend[0];
|
|
97
|
-
let endp = bgend[1];
|
|
98
|
-
if (!endp) {
|
|
99
|
-
endp = beginp;
|
|
100
|
-
}
|
|
101
|
-
//逗号分割开的某一区域 , , 被选定的: 页序数号是从开始的。
|
|
102
|
-
let i = Number(beginp);
|
|
103
|
-
const endpage = Number(endp);
|
|
104
|
-
if (i < 1 || i > allpagesum || endpage < i || endpage > allpagesum)
|
|
105
|
-
throw new Error("选定的页序号超范围:[" + i + "-" + endpage + "]");
|
|
106
|
-
for (; i <= endpage; i++) {
|
|
107
|
-
const [aPage] = await oneDoc.copyPages(srcDoc, [i - 1]);
|
|
108
|
-
oneDoc.addPage(aPage);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const name = CONFIG.APP.PATH + "/" + fileone.out + ".pdf";
|
|
112
|
-
fs.writeFileSync(name, await oneDoc.save());
|
|
113
|
-
}
|
|
114
|
-
} catch (e) {
|
|
115
|
-
result = "算失败了" + e;
|
|
116
|
-
console.error(e); //这个在最终服务端cmd窗口可输出
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (!result || result === "") result = "成功!";
|
|
120
|
-
res.status(OK).json(apiResponse({ result: result }));
|
|
121
|
-
} catch (error) {
|
|
122
|
-
next(error);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { query } from "express-validator";
|
|
2
|
-
import CONFIG from "../../configEnv";
|
|
3
|
-
|
|
4
|
-
const appKeys = Object.keys(CONFIG.APP).map((key) => key.toLocaleLowerCase());
|
|
5
|
-
|
|
6
|
-
export const appKeyValidator = [
|
|
7
|
-
query("key")
|
|
8
|
-
.optional()
|
|
9
|
-
.isString()
|
|
10
|
-
.isIn(appKeys)
|
|
11
|
-
.withMessage("`name` should be string type"),
|
|
12
|
-
];
|
package/src/configEnv/index.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import pkg from "../../package.json";
|
|
2
|
-
|
|
3
|
-
// https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
5
|
-
require("dotenv").config();
|
|
6
|
-
|
|
7
|
-
//提取独立的配置文件的设置参数:
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
9
|
-
const config = require("config");
|
|
10
|
-
const base_path = config.get("base_path");
|
|
11
|
-
const default_file = config.get("default_file");
|
|
12
|
-
console.log("默认合并输出文件: " + base_path + "/" + default_file + ".pdf");
|
|
13
|
-
|
|
14
|
-
//pkg.是项目工程的配置;
|
|
15
|
-
const CONFIG = {
|
|
16
|
-
APP: {
|
|
17
|
-
NAME: pkg.name,
|
|
18
|
-
VERSION: pkg.version,
|
|
19
|
-
VER: `v${pkg.version[0]}`,
|
|
20
|
-
DESCRIPTION: pkg.description,
|
|
21
|
-
AUTHORS: pkg.authors,
|
|
22
|
-
HOST: process.env.APP_HOST,
|
|
23
|
-
BASE_URL: process.env.API_BASE_URL,
|
|
24
|
-
PORT: process.env.NODE_ENV === "test" ? 8888 : process.env.PORT || 8080,
|
|
25
|
-
ENV: process.env.NODE_ENV,
|
|
26
|
-
PATH: base_path,
|
|
27
|
-
MERGE: default_file,
|
|
28
|
-
},
|
|
29
|
-
SERVER: {
|
|
30
|
-
TIMEOUT: 60 * 60 * 1000, // 60 *60秒没结果的
|
|
31
|
-
},
|
|
32
|
-
LOG: {
|
|
33
|
-
PATH: process.env.LOGGING_DIR || "logs",
|
|
34
|
-
LEVEL: process.env.LOGGING_LEVEL || "info",
|
|
35
|
-
MAX_FILES: process.env.LOGGING_MAX_FILES || 5,
|
|
36
|
-
},
|
|
37
|
-
AUTH: {
|
|
38
|
-
SALT_ROUNDS: process.env.SALT_ROUNDS || "11",
|
|
39
|
-
ACCESS_TOKEN_EXPIRE: process.env.ACCESS_TOKEN_DURATION || "300000",
|
|
40
|
-
REFRESH_TOKEN_EXPIRE: process.env.REFRESH_TOKEN_DURATION || "86400000",
|
|
41
|
-
ACCESS_TOKEN_SALT: process.env.ACCESS_TOKEN_SALT,
|
|
42
|
-
REFRESH_TOKEN_SALT: process.env.REFRESH_TOKEN_SALT,
|
|
43
|
-
},
|
|
44
|
-
AWS: {
|
|
45
|
-
ACCESS_KEY: process.env.AWS_ACCESS_KEY,
|
|
46
|
-
SECRET_KEY: process.env.AWS_SECRET_KEY,
|
|
47
|
-
REGION: process.env.AWS_REGION,
|
|
48
|
-
S3: {
|
|
49
|
-
PATH: process.env.S3_BUCKET_PATH,
|
|
50
|
-
BUCKET_NAME: process.env.S3_BUCKET_NAME,
|
|
51
|
-
},
|
|
52
|
-
COGNITO: {
|
|
53
|
-
USER_POOL_ID: process.env.COGNITO_USER_POOL_ID,
|
|
54
|
-
CLIENT_ID: process.env.COGNITO_CLIENT_ID,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
EXTERNAL: {
|
|
58
|
-
API_KEY: process.env.API_KEY,
|
|
59
|
-
},
|
|
60
|
-
} as const;
|
|
61
|
-
|
|
62
|
-
export default CONFIG;
|
package/src/db/home.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import AppInformation from "../types/response/AppInformation";
|
|
2
|
-
import CONFIG from "../configEnv";
|
|
3
|
-
import { getAppInfoQuery } from "../types/request/home";
|
|
4
|
-
|
|
5
|
-
export class HomeDAO {
|
|
6
|
-
get = (key?: getAppInfoQuery): Promise<AppInformation | any> => {
|
|
7
|
-
if (!key) {
|
|
8
|
-
return Promise.resolve(CONFIG.APP);
|
|
9
|
-
}
|
|
10
|
-
const upperKey = key.toUpperCase() as keyof typeof CONFIG.APP;
|
|
11
|
-
|
|
12
|
-
return Promise.resolve({ [upperKey]: CONFIG.APP[upperKey] });
|
|
13
|
-
};
|
|
14
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import HttpStatus, { OK } from "http-status/lib";
|
|
2
|
-
import { ApiSuccessResponse } from "../types/response";
|
|
3
|
-
|
|
4
|
-
export const apiResponse = <T>(data?: T): ApiSuccessResponse<T> => {
|
|
5
|
-
return {
|
|
6
|
-
status: OK,
|
|
7
|
-
message: HttpStatus[OK] as string,
|
|
8
|
-
data,
|
|
9
|
-
};
|
|
10
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Result, ValidationChain, validationResult } from "express-validator";
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
import { Middleware as ValidatorMiddleware } from "express-validator/src/base";
|
|
4
|
-
import ValidationError from "./error/ValidationError";
|
|
5
|
-
|
|
6
|
-
type MultiValidatorChain = ValidatorMiddleware & {
|
|
7
|
-
run: (req: Request) => Promise<Result>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const catchValidatorError = (req: Req, _: Res, next: NextFn): void => {
|
|
11
|
-
const errors = validationResult(req);
|
|
12
|
-
if (!errors.isEmpty()) {
|
|
13
|
-
const validationErrors = errors
|
|
14
|
-
.array()
|
|
15
|
-
.reduce(
|
|
16
|
-
(
|
|
17
|
-
obj: Record<string, string>,
|
|
18
|
-
error: Record<string, any>,
|
|
19
|
-
): Record<string, any> => {
|
|
20
|
-
obj[error.param] = error.msg;
|
|
21
|
-
return obj;
|
|
22
|
-
},
|
|
23
|
-
{},
|
|
24
|
-
);
|
|
25
|
-
throw new ValidationError(validationErrors);
|
|
26
|
-
}
|
|
27
|
-
next();
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const sanitizer = (
|
|
31
|
-
validator: (ValidationChain | MultiValidatorChain)[],
|
|
32
|
-
) => [...validator, catchValidatorError];
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import HttpStatus, { INTERNAL_SERVER_ERROR } from "http-status/lib";
|
|
2
|
-
|
|
3
|
-
class APIError extends Error {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly message: string;
|
|
6
|
-
readonly error: any | undefined;
|
|
7
|
-
|
|
8
|
-
constructor(message: string | null, error?: any) {
|
|
9
|
-
super();
|
|
10
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
11
|
-
this.status = INTERNAL_SERVER_ERROR;
|
|
12
|
-
this.message = message || (HttpStatus[INTERNAL_SERVER_ERROR] as string);
|
|
13
|
-
if (error && error instanceof Error) {
|
|
14
|
-
this.error = {
|
|
15
|
-
type: error?.name,
|
|
16
|
-
message: error?.message,
|
|
17
|
-
stack: error?.stack,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
Error.captureStackTrace(this);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default APIError;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { FORBIDDEN } from "http-status/lib";
|
|
2
|
-
|
|
3
|
-
class ForbiddenError {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly message: string;
|
|
6
|
-
|
|
7
|
-
constructor(message: string) {
|
|
8
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
-
|
|
10
|
-
this.status = FORBIDDEN;
|
|
11
|
-
this.message = message;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default ForbiddenError;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import HttpStatus, { NOT_FOUND } from "http-status/lib";
|
|
2
|
-
|
|
3
|
-
class NotFoundException {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly message: string;
|
|
6
|
-
|
|
7
|
-
constructor() {
|
|
8
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
-
|
|
10
|
-
this.status = NOT_FOUND;
|
|
11
|
-
this.message = HttpStatus[NOT_FOUND] as string;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default NotFoundException;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import httpStatus, { REQUEST_TIMEOUT } from "http-status/lib";
|
|
2
|
-
import CONFIG from "../../configEnv";
|
|
3
|
-
|
|
4
|
-
class TimeOutError {
|
|
5
|
-
readonly status: number;
|
|
6
|
-
readonly message: string;
|
|
7
|
-
readonly timeout: string | number;
|
|
8
|
-
readonly path: string;
|
|
9
|
-
|
|
10
|
-
constructor(path: string) {
|
|
11
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
-
|
|
13
|
-
this.status = REQUEST_TIMEOUT;
|
|
14
|
-
this.message = httpStatus[REQUEST_TIMEOUT] as string;
|
|
15
|
-
this.timeout = CONFIG.SERVER.TIMEOUT;
|
|
16
|
-
this.path = path;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default TimeOutError;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import HttpStatus, { UNAUTHORIZED } from "http-status/lib";
|
|
2
|
-
|
|
3
|
-
class UnauthorizedError {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly message: string;
|
|
6
|
-
|
|
7
|
-
constructor(message: string) {
|
|
8
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
-
|
|
10
|
-
this.status = UNAUTHORIZED;
|
|
11
|
-
this.message = message || (HttpStatus[UNAUTHORIZED] as string);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default UnauthorizedError;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import HttpStatus, { BAD_REQUEST } from "http-status/lib";
|
|
2
|
-
|
|
3
|
-
class ValidationError extends Error {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly message: string;
|
|
6
|
-
readonly details: Record<string, any>;
|
|
7
|
-
|
|
8
|
-
constructor(validationErrors: Record<string, any>) {
|
|
9
|
-
super();
|
|
10
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
11
|
-
|
|
12
|
-
this.status = BAD_REQUEST;
|
|
13
|
-
this.message = HttpStatus[BAD_REQUEST] as string;
|
|
14
|
-
this.details = validationErrors;
|
|
15
|
-
|
|
16
|
-
Error.captureStackTrace(this);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default ValidationError;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import APIError from "./ApiError";
|
|
2
|
-
import ValidationError from "./ValidationError";
|
|
3
|
-
import ForbiddenError from "./ForbiddenError";
|
|
4
|
-
import UnauthorizedError from "./UnauthorizedError";
|
|
5
|
-
import NotFoundException from "./NotFoundException";
|
|
6
|
-
import TimeOutError from "./TimeOutError";
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
APIError,
|
|
10
|
-
ValidationError,
|
|
11
|
-
ForbiddenError,
|
|
12
|
-
UnauthorizedError,
|
|
13
|
-
NotFoundException,
|
|
14
|
-
TimeOutError,
|
|
15
|
-
};
|
package/src/helpers/index.ts
DELETED
package/src/helpers/loggers.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import httpStatus from "http-status/lib";
|
|
2
|
-
import expressPino from "express-pino-logger";
|
|
3
|
-
import { hidePassword } from "../utils/auth";
|
|
4
|
-
|
|
5
|
-
const { OK, BAD_REQUEST } = httpStatus;
|
|
6
|
-
|
|
7
|
-
// More info: https://github.com/pinojs/express-pino-logger
|
|
8
|
-
export const expressPinoLogger = () =>
|
|
9
|
-
expressPino({
|
|
10
|
-
transport: {
|
|
11
|
-
target: "pino-pretty",
|
|
12
|
-
options: {
|
|
13
|
-
colorize: true,
|
|
14
|
-
translateTime: true,
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
customLogLevel(res, err) {
|
|
18
|
-
const status = res.statusCode!;
|
|
19
|
-
if (status >= 400 && status < 500) {
|
|
20
|
-
return "warn";
|
|
21
|
-
}
|
|
22
|
-
if (status >= 500 || err) {
|
|
23
|
-
return "error";
|
|
24
|
-
}
|
|
25
|
-
return "silent";
|
|
26
|
-
},
|
|
27
|
-
customErrorMessage: (err) => ` : ${err}`,
|
|
28
|
-
customSuccessMessage(res) {
|
|
29
|
-
const status = res.statusCode!;
|
|
30
|
-
if (status >= 400 && status < 500) {
|
|
31
|
-
// @ts-ignore
|
|
32
|
-
return `${status || BAD_REQUEST} : ${httpStatus[status || 400]}`;
|
|
33
|
-
}
|
|
34
|
-
if (status >= 500) {
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
return `${status} : ${httpStatus[status || 500]}`;
|
|
37
|
-
}
|
|
38
|
-
return `${OK} : ${httpStatus[200].toUpperCase()}`;
|
|
39
|
-
},
|
|
40
|
-
serializers: {
|
|
41
|
-
req: (req) => {
|
|
42
|
-
// console.log('[ R E Q U E S T ] => ', req.raw);
|
|
43
|
-
const {
|
|
44
|
-
method,
|
|
45
|
-
url,
|
|
46
|
-
headers: { host },
|
|
47
|
-
} = req;
|
|
48
|
-
return {
|
|
49
|
-
origin: host,
|
|
50
|
-
method,
|
|
51
|
-
url,
|
|
52
|
-
query: req.query,
|
|
53
|
-
params: req.params,
|
|
54
|
-
body: hidePassword({ ...req.raw.body }),
|
|
55
|
-
};
|
|
56
|
-
},
|
|
57
|
-
res: (res) => {
|
|
58
|
-
// console.log("[ R E S P O N S E ] => ", res);
|
|
59
|
-
return {
|
|
60
|
-
status: res.statusCode,
|
|
61
|
-
};
|
|
62
|
-
},
|
|
63
|
-
err: (err) => `${err.type} : ${err.message}`,
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export const exitLog = (err: any, evt: string) => {
|
|
68
|
-
if (err) {
|
|
69
|
-
process.stdout.write(`\n\n[!ERROR][${evt}] => ${err}\n\n`);
|
|
70
|
-
} else {
|
|
71
|
-
process.stdout.write(`\n\n![${evt}] EVENT CAUSE EXIT\n\n`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
process.exit(err ? 1 : 0);
|
|
75
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from "express";
|
|
2
|
-
|
|
3
|
-
import HttpStatus, {
|
|
4
|
-
NOT_FOUND,
|
|
5
|
-
INTERNAL_SERVER_ERROR,
|
|
6
|
-
REQUEST_TIMEOUT,
|
|
7
|
-
} from "http-status/lib";
|
|
8
|
-
import { TimeOutError } from "../helpers/error";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @description Error response middleware for 404 not found. This middleware function should be at the very bottom of the stack.
|
|
12
|
-
* @param req Express.Request
|
|
13
|
-
* @param res Express.Response
|
|
14
|
-
* @param _next Express.NextFunction
|
|
15
|
-
*/
|
|
16
|
-
export const notFoundError = (
|
|
17
|
-
req: Request,
|
|
18
|
-
res: Response,
|
|
19
|
-
_next: NextFunction,
|
|
20
|
-
) => {
|
|
21
|
-
res.status(NOT_FOUND).json({
|
|
22
|
-
error: {
|
|
23
|
-
code: NOT_FOUND,
|
|
24
|
-
message: HttpStatus[NOT_FOUND],
|
|
25
|
-
path: req.originalUrl,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @description Generic error response middleware for validation and internal server errors.
|
|
32
|
-
* @param {*} err
|
|
33
|
-
* @param {object} req Express.Request
|
|
34
|
-
* @param {object} res Express.Response
|
|
35
|
-
* @param {function} next Express.NextFunction
|
|
36
|
-
*/
|
|
37
|
-
export const genericErrorHandler = (
|
|
38
|
-
err: any,
|
|
39
|
-
req: Request,
|
|
40
|
-
res: Response,
|
|
41
|
-
_next: NextFunction,
|
|
42
|
-
) => {
|
|
43
|
-
let resCode: number = err.status || INTERNAL_SERVER_ERROR;
|
|
44
|
-
let resBody = err;
|
|
45
|
-
|
|
46
|
-
if (err.code === "ETIMEDOUT") {
|
|
47
|
-
resCode = REQUEST_TIMEOUT;
|
|
48
|
-
resBody = new TimeOutError(req.originalUrl);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
res.status(resCode).json(resBody);
|
|
52
|
-
};
|