page2pdf_server 1.0.0

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.
Files changed (79) hide show
  1. package/.babelrc +3 -0
  2. package/.eslintrc +33 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  5. package/.github/ISSUE_TEMPLATE/refactoring.md +15 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  7. package/.github/stale.yml +17 -0
  8. package/.github/workflows/cd.yml +75 -0
  9. package/.github/workflows/ci.yml +36 -0
  10. package/.husky/pre-commit +6 -0
  11. package/.husky/pre-push +4 -0
  12. package/.idea/codeStyles/Project.xml +58 -0
  13. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  14. package/.idea/encodings.xml +7 -0
  15. package/.idea/inspectionProfiles/Project_Default.xml +7 -0
  16. package/.idea/modules.xml +8 -0
  17. package/.idea/page2pdf-server.iml +12 -0
  18. package/.idea/tenstack-starter-main.iml +12 -0
  19. package/.idea/vcs.xml +6 -0
  20. package/.prettierrc +8 -0
  21. package/.vscode/settings.json +3 -0
  22. package/LICENSE +18 -0
  23. package/README.md +238 -0
  24. package/__tests__/UrltoPdf/generatePdf.test.ts +207 -0
  25. package/__tests__/UrltoPdf/pdfSplit.test.ts +69 -0
  26. package/__tests__/helpers/index.ts +21 -0
  27. package/__tests__/home.test.ts +77 -0
  28. package/config/default.json +10 -0
  29. package/config/development.json +3 -0
  30. package/config/production.json +3 -0
  31. package/config/test.json +3 -0
  32. package/ecosystem.config.js +41 -0
  33. package/eslintrc.json +14 -0
  34. package/jest.config.js +35 -0
  35. package/nodemon.json +6 -0
  36. package/package.json +105 -0
  37. package/src/CSS/345/205/274/345/256/271/346/200/247.txt +56 -0
  38. package/src/app.ts +41 -0
  39. package/src/components/home/controller.ts +27 -0
  40. package/src/components/home/index.ts +4 -0
  41. package/src/components/home/pdfController.ts +112 -0
  42. package/src/components/home/services.ts +31 -0
  43. package/src/components/home/splitController.ts +124 -0
  44. package/src/components/home/validators.ts +12 -0
  45. package/src/configEnv/index.ts +62 -0
  46. package/src/db/home.ts +14 -0
  47. package/src/helpers/apiResponse.ts +10 -0
  48. package/src/helpers/dataSanitizers.ts +31 -0
  49. package/src/helpers/error/ApiError.ts +25 -0
  50. package/src/helpers/error/ForbiddenError.ts +15 -0
  51. package/src/helpers/error/NotFoundException.ts +15 -0
  52. package/src/helpers/error/TimeOutError.ts +20 -0
  53. package/src/helpers/error/UnauthorizedError.ts +15 -0
  54. package/src/helpers/error/ValidationError.ts +20 -0
  55. package/src/helpers/error/index.ts +15 -0
  56. package/src/helpers/index.ts +2 -0
  57. package/src/helpers/loggers.ts +73 -0
  58. package/src/index.ts +13 -0
  59. package/src/middlewares/errorHandler.ts +52 -0
  60. package/src/new_tab1.mhtml +722 -0
  61. package/src/routes/index.ts +22 -0
  62. package/src/server.ts +30 -0
  63. package/src/testCSS.html +241 -0
  64. package/src/types/global.d.ts +13 -0
  65. package/src/types/request/home.ts +166 -0
  66. package/src/types/request/split.ts +18 -0
  67. package/src/types/response/AppInformation.ts +9 -0
  68. package/src/types/response/index.ts +5 -0
  69. package/src/utils/array.ts +19 -0
  70. package/src/utils/auth.ts +12 -0
  71. package/src/utils/crypt.ts +26 -0
  72. package/src/utils/filter.ts +59 -0
  73. package/src/utils/object.ts +58 -0
  74. package/src/utils/pdfgen.ts +998 -0
  75. package/src/utils/url.ts +54 -0
  76. package/src//346/265/213/350/257/225.txt +241 -0
  77. package/tsconfig.json +41 -0
  78. package/tslint.json +22 -0
  79. package//346/226/207/344/271/246/346/211/223/345/215/260/350/275/254/346/215/242/345/231/250.bat +2 -0
@@ -0,0 +1,62 @@
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 ADDED
@@ -0,0 +1,14 @@
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
+ }
@@ -0,0 +1,10 @@
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
+ };
@@ -0,0 +1,31 @@
1
+ import { Result, ValidationChain, validationResult } from "express-validator";
2
+ import { Middleware as ValidatorMiddleware } from "express-validator/src/base";
3
+ import ValidationError from "./error/ValidationError";
4
+
5
+ type MultiValidatorChain = ValidatorMiddleware & {
6
+ run: (req: Request) => Promise<Result>;
7
+ };
8
+
9
+ const catchValidatorError = (req: Req, _: Res, next: NextFn): void => {
10
+ const errors = validationResult(req);
11
+ if (!errors.isEmpty()) {
12
+ const validationErrors = errors
13
+ .array()
14
+ .reduce(
15
+ (
16
+ obj: Record<string, string>,
17
+ error: Record<string, any>,
18
+ ): Record<string, any> => {
19
+ obj[error.param] = error.msg;
20
+ return obj;
21
+ },
22
+ {},
23
+ );
24
+ throw new ValidationError(validationErrors);
25
+ }
26
+ next();
27
+ };
28
+
29
+ export const sanitizer = (
30
+ validator: (ValidationChain | MultiValidatorChain)[],
31
+ ) => [...validator, catchValidatorError];
@@ -0,0 +1,25 @@
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;
@@ -0,0 +1,15 @@
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;
@@ -0,0 +1,15 @@
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;
@@ -0,0 +1,20 @@
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;
@@ -0,0 +1,15 @@
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;
@@ -0,0 +1,20 @@
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;
@@ -0,0 +1,15 @@
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
+ };
@@ -0,0 +1,2 @@
1
+ export { expressPinoLogger, exitLog } from "./loggers";
2
+ export { sanitizer } from "./dataSanitizers";
@@ -0,0 +1,73 @@
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, SERVER_ERROR } = 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
+ return `${status || BAD_REQUEST} : ${httpStatus[status || 400]}`;
32
+ }
33
+ if (status >= 500) {
34
+ return `${status || SERVER_ERROR} : ${httpStatus[status || 500]}`;
35
+ }
36
+ return `${OK} : ${httpStatus[200].toUpperCase()}`;
37
+ },
38
+ serializers: {
39
+ req: (req) => {
40
+ // console.log('[ R E Q U E S T ] => ', req.raw);
41
+ const {
42
+ method,
43
+ url,
44
+ headers: { host },
45
+ } = req;
46
+ return {
47
+ origin: host,
48
+ method,
49
+ url,
50
+ query: req.query,
51
+ params: req.params,
52
+ body: hidePassword({ ...req.raw.body }),
53
+ };
54
+ },
55
+ res: (res) => {
56
+ // console.log("[ R E S P O N S E ] => ", res);
57
+ return {
58
+ status: res.statusCode,
59
+ };
60
+ },
61
+ err: (err) => `${err.type} : ${err.message}`,
62
+ },
63
+ });
64
+
65
+ export const exitLog = (err: any, evt: string) => {
66
+ if (err) {
67
+ process.stdout.write(`\n\n[!ERROR][${evt}] => ${err}\n\n`);
68
+ } else {
69
+ process.stdout.write(`\n\n![${evt}] EVENT CAUSE EXIT\n\n`);
70
+ }
71
+
72
+ process.exit(err ? 1 : 0);
73
+ };
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ // ! Don't convert require into import
2
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
3
+ require("module-alias").addAlias("@", __dirname);
4
+
5
+ import { createApp } from "./app";
6
+ import { startServer } from "./server";
7
+
8
+ if (process.env.NODE_ENV !== "test") {
9
+ const app = createApp();
10
+ startServer(app);
11
+ }
12
+
13
+ //关键文档Chrome DevTools Protocol资料, https://chromedevtools.github.io/devtools-protocol/tot/Page
@@ -0,0 +1,52 @@
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
+ };