mas-server 2.0.52 → 2.0.54

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/dist/index.js CHANGED
@@ -9,7 +9,7 @@ const express_1 = __importDefault(require("express"));
9
9
  const cors_1 = __importDefault(require("cors"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const state_1 = require("./state");
12
- const getLog_1 = __importDefault(require("./utils/getLog"));
12
+ const printLog_1 = __importDefault(require("./utils/printLog"));
13
13
  const quickSend_1 = __importDefault(require("./utils/quickSend"));
14
14
  const readApi_1 = __importDefault(require("./utils/readApi"));
15
15
  exports.readApi = readApi_1.default;
@@ -39,8 +39,11 @@ const validType_1 = __importDefault(require("./utils/validType"));
39
39
  exports.validType = validType_1.default;
40
40
  const createRouter_1 = __importDefault(require("./utils/createRouter"));
41
41
  const getRouterInfo_1 = __importDefault(require("./utils/getRouterInfo"));
42
+ const logs_1 = __importDefault(require("./utils/logs"));
43
+ const apiLimit_1 = __importDefault(require("./utils/apiLimit"));
42
44
  // =================================================================
43
45
  function getApp(DIRNAME, beforeMounted) {
46
+ var _a;
44
47
  // 路径和配置放入state
45
48
  state_1.state.DIRNAME = DIRNAME;
46
49
  const config = require(path_1.default.join(DIRNAME, "/config/config.ts")).default;
@@ -50,6 +53,10 @@ function getApp(DIRNAME, beforeMounted) {
50
53
  state_1.state.apiCN = [];
51
54
  // new express
52
55
  const app = (0, express_1.default)();
56
+ // ip限制
57
+ if ((_a = config.apiLimit) === null || _a === void 0 ? void 0 : _a.open) {
58
+ (0, apiLimit_1.default)(app, config.apiLimit || {});
59
+ }
53
60
  // 是否允许跨域
54
61
  config.cors && app.use((0, cors_1.default)());
55
62
  if (beforeMounted) {
@@ -67,10 +74,15 @@ function getApp(DIRNAME, beforeMounted) {
67
74
  });
68
75
  //快速return
69
76
  app.use(quickSend_1.default);
70
- // 日志
71
- if (config.logs.open) {
77
+ // 打印日志
78
+ if (config.logs.debug) {
72
79
  app.use(require("express-ip")().getIpInfoMiddleware);
73
- app.use(getLog_1.default);
80
+ app.use(printLog_1.default);
81
+ }
82
+ // 存储日志
83
+ if (config.logs.open) {
84
+ // app.use(printLog);
85
+ (0, logs_1.default)(app, path_1.default.join(DIRNAME + `/logs/`));
74
86
  }
75
87
  // 权限管理
76
88
  if (config.token.open) {
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
7
+ const apiLimit = (app, config) => {
8
+ // 创建一个速率限制器,限制每个IP地址在一分钟内最多可以发送10个请求
9
+ const limiter = (0, express_rate_limit_1.default)({
10
+ windowMs: (config === null || config === void 0 ? void 0 : config.windowMs) || 60 * 1000,
11
+ max: (config === null || config === void 0 ? void 0 : config.max) || 20,
12
+ // 当达到限制时调用的处理函数
13
+ handler: function (req, res) {
14
+ res.status(502).end();
15
+ },
16
+ });
17
+ // 将速率限制器应用于所有请求
18
+ app.use(limiter);
19
+ };
20
+ exports.default = apiLimit;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const state_1 = require("@/state");
6
+ const state_1 = require("../state");
7
7
  const readApi_1 = __importDefault(require("./readApi"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const fs_1 = __importDefault(require("fs"));
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const morgan_1 = __importDefault(require("morgan"));
30
+ const fs_1 = __importDefault(require("fs"));
31
+ const rfs = __importStar(require("rotating-file-stream"));
32
+ const getLogs = (app, dir) => {
33
+ // 创建一个日志目录(如果它不存在的话)
34
+ const logDirectory = dir;
35
+ fs_1.default.existsSync(logDirectory) || fs_1.default.mkdirSync(logDirectory);
36
+ // 创建一个循环日志流
37
+ const accessLogStream = rfs.createStream("access.log", {
38
+ size: "50M",
39
+ interval: "1d",
40
+ path: logDirectory,
41
+ });
42
+ app.use((0, morgan_1.default)("combined", { stream: accessLogStream }));
43
+ };
44
+ exports.default = getLogs;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const moment_1 = __importDefault(require("moment"));
7
+ exports.default = (req, res, next) => {
8
+ const date = (0, moment_1.default)().format("YYYY-MM-DD HH:mm:ss");
9
+ const data = `${date} ${req.method} ${req.ipInfo.ip} ${req.url} ${req.body ? JSON.stringify(req.body) : ""}\n`;
10
+ console.info(data);
11
+ next();
12
+ };
package/package.json CHANGED
@@ -1,50 +1,52 @@
1
- {
2
- "name": "mas-server",
3
- "version": "2.0.52",
4
- "description": "一款基于express面向中小型项目的后端框架",
5
- "main": "dist/index.js",
6
- "typings": "src/index.ts",
7
- "scripts": {
8
- "testdev": "npx ts-node-dev --transpile-only ./test/scripts/run.ts --respawn",
9
- "test": "npx ts-node ./test/scripts/beforeCreated.ts -end && npx ts-node ./test/scripts/run.ts",
10
- "testmon": "npx nodemon ./test/scripts/run.ts",
11
- "testTS": "npx nodemon ./test/test.ts",
12
- "createSql": "npx ts-node ./test/scripts/createSqlForm.ts",
13
- "createApi": "npx ts-node ./test/scripts/createApiFile.ts",
14
- "createApis": "npx ts-node ./test/scripts/createApis.ts",
15
- "init": "npx nodemon ./test/scripts/beforeCreated.ts -end",
16
- "gsft": "npx nodemon ./test/scripts/getSqlFormType.ts",
17
- "build": "tsc --project ./tsconfig-build.json",
18
- "sync": "npm run build && node ./beforebuild.js && npm publish && cnpm sync mas-server && explorer \"https://npmmirror.com/package/mas-server\""
19
- },
20
- "keywords": [],
21
- "author": "tingxi8087",
22
- "license": "ISC",
23
- "dependencies": {
24
- "@types/express": "^4.17.17",
25
- "ansi-colors": "^4.1.3",
26
- "axios": "^1.3.6",
27
- "cors": "^2.8.5",
28
- "express": "^4.18.2",
29
- "express-ip": "^1.0.4",
30
- "fs-extra": "^11.1.1",
31
- "glob": "^10.3.1",
32
- "masmysql": "^2.0.53",
33
- "module-alias": "^2.2.2",
34
- "moment": "^2.29.4",
35
- "mysql": "^2.18.1",
36
- "nodemon": "^2.0.22",
37
- "ts-node": "^10.9.1",
38
- "ts-node-dev": "^2.0.0",
39
- "typescript": "^5.0.4"
40
- },
41
- "_moduleAliases": {
42
- "@": "src/",
43
- "@@": "."
44
- },
45
- "devDependencies": {
46
- "@types/cors": "^2.8.13",
47
- "@types/express": "^4.17.17",
48
- "@types/moment": "^2.13.0"
49
- }
50
- }
1
+ {
2
+ "name": "mas-server",
3
+ "version": "2.0.54",
4
+ "description": "一款基于express面向中小型项目的后端框架",
5
+ "main": "dist/index.js",
6
+ "typings": "src/index.ts",
7
+ "scripts": {
8
+ "test": "npx ts-node ./test/scripts/beforeCreated.ts -end && npx ts-node ./test/scripts/run.ts",
9
+ "testmon": "npx nodemon ./test/scripts/run.ts",
10
+ "testTS": "npx nodemon ./test/test.ts",
11
+ "createSql": "npx ts-node ./test/scripts/createSqlForm.ts",
12
+ "createApi": "npx ts-node ./test/scripts/createApiFile.ts",
13
+ "createApis": "npx ts-node ./test/scripts/createApis.ts",
14
+ "init": "npx nodemon ./test/scripts/beforeCreated.ts -end",
15
+ "gsft": "npx nodemon ./test/scripts/getSqlFormType.ts",
16
+ "build": "tsc --project ./tsconfig-build.json",
17
+ "sync": "npm run build && node ./beforebuild.js && npm publish && cnpm sync mas-server && explorer \"https://npmmirror.com/package/mas-server\""
18
+ },
19
+ "keywords": [],
20
+ "author": "tingxi8087",
21
+ "license": "ISC",
22
+ "dependencies": {
23
+ "@types/express": "^4.17.17",
24
+ "ansi-colors": "^4.1.3",
25
+ "axios": "^1.3.6",
26
+ "cors": "^2.8.5",
27
+ "express": "^4.18.2",
28
+ "express-ip": "^1.0.4",
29
+ "express-rate-limit": "^7.1.4",
30
+ "fs-extra": "^11.1.1",
31
+ "glob": "^10.3.1",
32
+ "masmysql": "^2.0.53",
33
+ "module-alias": "^2.2.2",
34
+ "moment": "^2.29.4",
35
+ "morgan": "^1.10.0",
36
+ "mysql": "^2.18.1",
37
+ "nodemon": "^2.0.22",
38
+ "rotating-file-stream": "^3.1.1",
39
+ "ts-node": "^10.9.1",
40
+ "ts-node-dev": "^2.0.0",
41
+ "typescript": "^5.0.4"
42
+ },
43
+ "_moduleAliases": {
44
+ "@": "src/",
45
+ "@@": "."
46
+ },
47
+ "devDependencies": {
48
+ "@types/cors": "^2.8.13",
49
+ "@types/express": "^4.17.17",
50
+ "@types/moment": "^2.13.0"
51
+ }
52
+ }
package/src/index.ts CHANGED
@@ -5,11 +5,10 @@ import cors from "cors";
5
5
  import path from "path";
6
6
  import * as fs from "fs";
7
7
  import { state } from "./state";
8
- import getLog from "./utils/getLog";
8
+ import printLog from "./utils/printLog";
9
9
  import quickSend from "./utils/quickSend";
10
10
  import readApi from "./utils/readApi";
11
11
  import validRouteData from "./utils/validRouteData";
12
-
13
12
  import validTokenUse from "./utils/validToken";
14
13
  import type {
15
14
  masReq,
@@ -40,6 +39,8 @@ import { createToken, validToken } from "./utils/meaToken";
40
39
  import validType from "./utils/validType";
41
40
  import createRouter from "./utils/createRouter";
42
41
  import getRouterInfo from "./utils/getRouterInfo";
42
+ import getLogs from "./utils/logs";
43
+ import apiLimit from "./utils/apiLimit";
43
44
 
44
45
  // =================================================================
45
46
  export function getApp(
@@ -58,6 +59,10 @@ export function getApp(
58
59
  state.apiCN = [];
59
60
  // new express
60
61
  const app = express();
62
+ // ip限制
63
+ if (config.apiLimit?.open) {
64
+ apiLimit(app, config.apiLimit || {});
65
+ }
61
66
  // 是否允许跨域
62
67
  config.cors && app.use(cors());
63
68
  if (beforeMounted) {
@@ -75,11 +80,17 @@ export function getApp(
75
80
  });
76
81
  //快速return
77
82
  app.use(quickSend);
78
- // 日志
79
- if (config.logs.open) {
83
+ // 打印日志
84
+ if (config.logs.debug) {
80
85
  app.use(require("express-ip")().getIpInfoMiddleware);
81
- app.use(getLog);
86
+ app.use(printLog);
82
87
  }
88
+ // 存储日志
89
+ if (config.logs.open) {
90
+ // app.use(printLog);
91
+ getLogs(app, path.join(DIRNAME + `/logs/`));
92
+ }
93
+
83
94
  // 权限管理
84
95
  if (config.token.open) {
85
96
  app.use(validTokenUse);
@@ -85,13 +85,21 @@ export type configType = {
85
85
  };
86
86
  /** 是否允许跨域 */
87
87
  cors: boolean;
88
-
89
88
  logs: {
90
89
  /** 是否保存日志 */
91
90
  open: boolean;
92
91
  /** 是否打印访问日志 */
93
92
  debug: boolean;
94
93
  };
94
+ /** ip请求限制 */
95
+ apiLimit: {
96
+ /** 是否开启 */
97
+ open?: boolean;
98
+ /** 同个 ip windowMs ms之内 */
99
+ windowMs?: number;
100
+ /** 最多max个请求 */
101
+ max?: number; //
102
+ };
95
103
  token: {
96
104
  /** 是否使用token */
97
105
  open: boolean;
@@ -0,0 +1,15 @@
1
+ import rateLimit from "express-rate-limit";
2
+ const apiLimit = (app: any, config?: { windowMs: number; max: number }) => {
3
+ // 创建一个速率限制器,限制每个IP地址在一分钟内最多可以发送10个请求
4
+ const limiter = rateLimit({
5
+ windowMs: config?.windowMs || 60 * 1000, // 1分钟
6
+ max: config?.max || 20, // 最多10个请求
7
+ // 当达到限制时调用的处理函数
8
+ handler: function (req, res) {
9
+ res.status(502).end();
10
+ },
11
+ });
12
+ // 将速率限制器应用于所有请求
13
+ app.use(limiter);
14
+ };
15
+ export default apiLimit;
@@ -1,4 +1,4 @@
1
- import { state } from "@/state";
1
+ import { state } from "../state";
2
2
  import readFilesRecursively from "./readApi";
3
3
  import path from "path";
4
4
  import fs from "fs";
@@ -0,0 +1,17 @@
1
+ import rateLimit from "express-rate-limit";
2
+ import morgan from "morgan";
3
+ import fs from "fs";
4
+ import * as rfs from "rotating-file-stream";
5
+ const getLogs = (app: any, dir: string) => {
6
+ // 创建一个日志目录(如果它不存在的话)
7
+ const logDirectory = dir;
8
+ fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
9
+ // 创建一个循环日志流
10
+ const accessLogStream = rfs.createStream("access.log", {
11
+ size: "50M", // 单个文件的最大大小
12
+ interval: "1d", // 每天滚动日志
13
+ path: logDirectory,
14
+ });
15
+ app.use(morgan("combined", { stream: accessLogStream }));
16
+ };
17
+ export default getLogs;
@@ -3,18 +3,10 @@ import { state } from "../state";
3
3
  import moment from "moment";
4
4
 
5
5
  export default (req, res, next) => {
6
- const { config } = state;
7
6
  const date = moment().format("YYYY-MM-DD HH:mm:ss");
8
7
  const data = `${date} ${req.method} ${req.ipInfo.ip} ${req.url} ${
9
8
  req.body ? JSON.stringify(req.body) : ""
10
9
  }\n`;
11
- fs.appendFileSync(
12
- state.DIRNAME + `/logs/${moment().format("YYYY-MM-DD")}.log`,
13
- data
14
- );
15
-
16
- if (config.logs.debug) {
17
- console.info(data);
18
- }
10
+ console.info(data);
19
11
  next();
20
12
  };
@@ -12,12 +12,18 @@ export default <configType>{
12
12
  open: true,
13
13
  debug: false,
14
14
  },
15
+ apiLimit: {
16
+ open: true,
17
+ windowMs: 60 * 1000,
18
+ // windowMs: 60 * 1000,
19
+ max: 5,
20
+ },
15
21
  token: {
16
22
  open: true,
17
23
  pwd: "8087",
18
24
  headerParams: "token",
19
25
  },
20
- useSql: true,
26
+ useSql: false,
21
27
  debugTime: 100,
22
28
  sql: {
23
29
  host: "127.0.0.1",
@@ -1,20 +0,0 @@
1
- 约定式接口读取 完成
2
- 数据效验 完成
3
- masmysql引入 (massql set方法开发) 完成
4
- 权限管理,token生成 完成
5
- 接口文档生成 完成
6
- 快捷创建接口 完成
7
- 生成sql类型 完成
8
- 错误处理 完成
9
- cookie管理
10
- 路由导航汉化
11
- 接口文档体验优化
12
- .vscode配置
13
- 一键导出前端axios代码
14
- 接口加载状态
15
- 导航点击跳转 调试->调试
16
- 特别说明:
17
- get请求和请求头的number参数会被转为string,get请求无法发送和接收数组
18
- 接口改名配置丢失
19
- 只能接收{}或[]
20
- 请求参数必须是对象或数组