streamline-code-by-ikun2274 0.11.1

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/Develop-log.md ADDED
@@ -0,0 +1,47 @@
1
+ ### 更新时间- 2026.4.4 12:00
2
+ #### 当前版本是 0.11.1
3
+
4
+ ```
5
+ //1. 单个中间件
6
+
7
+ DefineRoutePlus_A({
8
+ url: '/api/products',
9
+ method: 'get',
10
+ BuiltinMid: {
11
+ Parameter: 'requireAuth'
12
+ },
13
+ PlusHandler: {
14
+ db: { table: 'products', operation: 'read' },
15
+ other: { successMessage: '获取商品列表成功' }
16
+ }
17
+ });
18
+
19
+ //带参数的中间件
20
+ DefineRoutePlus_A({
21
+ url: '/api/products',
22
+ method: 'get',
23
+ BuiltinMid: {
24
+ Parameter: 'pagination:20' // 分页,每页20条
25
+ },
26
+ PlusHandler: {
27
+ db: { table: 'products', operation: 'read' },
28
+ other: { successMessage: '获取商品列表成功' }
29
+ }
30
+ });
31
+
32
+ //多个中间件
33
+ DefineRoutePlus_A({
34
+ url: '/api/products',
35
+ method: 'get',
36
+ BuiltinMid: {
37
+ Parameter: ['requireAuth', 'pagination:20', 'shuffle']
38
+ },
39
+ PlusHandler: {
40
+ db: { table: 'products', operation: 'read' },
41
+ other: { successMessage: '获取商品列表成功' }
42
+ }
43
+ });
44
+ ```
45
+
46
+ ### 松烟迭代了当前项目的 字符串正则匹配字符串,通过这个激活中间件,你可以按需要搭配我的内置中间件了
47
+ -- 想迭代为express 生态 gitee仓库 10k star的第一天
package/Example.js ADDED
@@ -0,0 +1,100 @@
1
+ import { setDbConfig,startServer,DefineRoutePlus_A } from './src/StreamlineCodeIndex.js';
2
+
3
+
4
+
5
+
6
+ setDbConfig({
7
+ /**
8
+ *
9
+ * host: 'your-host',
10
+ user: 'your-username',
11
+ password: 'your-password',
12
+ database: 'your-database'
13
+ *
14
+ */
15
+
16
+ host: 'localhost',
17
+ user: 'root', // 你的 MySQL 用户名
18
+ password: '123456', // 你的 MySQL 密码
19
+ database: 'my_test_db' // 数据库名
20
+
21
+ })
22
+
23
+
24
+ startServer({
25
+ port: 8008, // 端口配置
26
+ allowedOrigins: [ // 允许的域名
27
+ 'http://127.0.0.1:5501',
28
+ 'http://ztgame.click',
29
+ 'http://60.205.158.63',
30
+ 'http://localhost:5173'
31
+ ]
32
+ });
33
+
34
+
35
+ DefineRoutePlus_A({
36
+
37
+ /**
38
+ * 二次封装 defineRoute 函数
39
+ * {Object} options - 路由配置选项
40
+ * {string} options.url - 路由路径(必填)
41
+ * {string} options.method - HTTP 方法(GET/POST/PUT/DELETE,必填)
42
+ * {Array<Function>} [options.middlewares=[]] - 中间件数组(可选)
43
+ * {Function} options.handler - 业务逻辑处理函数(async (req) => data,必填)
44
+ * {Object} options.PlusHandler - 额外处理选项(必填)
45
+ * {Object} options.PlusHandler.db - 数据库操作(必填)select/insert/update/update/delete
46
+ * {string} options.PlusHandler.db.table - 数据库表名(必填)
47
+ * {string} options.PlusHandler.db.operation - 数据库操作(必填)
48
+ * {string} [options.PlusHandler.db.primaryKey='id'] - 主键字段(可选)
49
+ * {string} [options.PlusHandler.db.fields='*'] - 查询字段(可选)
50
+ * {string} [options.PlusHandler.db.categoryField='category_id'] - 分类字段(可选)
51
+ * {Object} options.PlusHandler.Mode - 模式选项(必填)
52
+ * {boolean} [options.PlusHandler.Mode.pagination=false] - 是否支持分页(可选)
53
+ * {boolean} [options.PlusHandler.Mode.requireAuth=false] - 是否需要身份验证(可选)
54
+ * {boolean} [options.PlusHandler.Mode.shuffle=false] - 是否打乱数据(可选)
55
+ * {number} [options.PlusHandler.Mode.pageSize=10] - 每页大小(可选)
56
+ * {Object} options.PlusHandler.other - 其他选项(必填)
57
+ * {string} [options.PlusHandler.other.successMessage='操作成功'] - 成功消息(可选)
58
+ * {string} [options.PlusHandler.other.errorMessage='操作失败'] - 错误消息(可选)
59
+ * */
60
+
61
+
62
+ url: '/api/productlist',
63
+ //请求方法
64
+ method: 'get',
65
+ //内置方法
66
+ PlusHandler: {
67
+ //数据表操作
68
+ db: {
69
+ table: 'product',
70
+ operation: 'select',//select/insert/update/update/delete
71
+ primaryKey: 'id',
72
+ fields: '*',
73
+ },
74
+ Mode: {
75
+ pagination: true,
76
+ requireAuth: false,
77
+ shuffle: false,
78
+ pageSize: 10
79
+
80
+ },
81
+ //其他
82
+ other: {
83
+ successMessage: '操作成功',
84
+ errorMessage: '操作失败'
85
+ }
86
+ }
87
+
88
+
89
+
90
+ /**
91
+ *
92
+ *
93
+ *
94
+ */
95
+ });
96
+
97
+
98
+
99
+
100
+
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ ## 项目介绍 express-lowcode-by-ikun2274
2
+
3
+
4
+ ## 开发日志
5
+ 详细的开发历程和版本更新记录,请查看 [开发日志](Develop-log.md)。
6
+
7
+
8
+ ### 基本介绍
9
+
10
+ ```
11
+ express-lowcode-by-ikun2274 是一个基于 Express 的低代码路由构建工具,
12
+ 用于快速构建数据库操作、分页、认证等路由。
13
+ ```
14
+
15
+
16
+
17
+
18
+
19
+ ## npm的地址
20
+
21
+ ```
22
+ https://www.npmjs.com/package/express-lowcode-by-ikun2274
23
+ ```
24
+
25
+ ### 示例代码-
26
+
27
+ ```
28
+ 你可以在npm安装之后 有一个叫做Example.js的文件 它是一个示例代码
29
+ 你可以参考它来快速构建自己的路由 之后我自己会在项目里面塞上示例代码文件夹的
30
+
31
+ 你可以这样子写 Example.js是这样子的
32
+
33
+
34
+ import { setDbConfig,startServer,DefineRoutePlus_A } from './src/LowCodeIndex.js';
35
+
36
+
37
+
38
+
39
+ setDbConfig({
40
+ /**
41
+ *
42
+ * host: 'your-host',
43
+ user: 'your-username',
44
+ password: 'your-password',
45
+ database: 'your-database'
46
+ *
47
+ */
48
+
49
+ host: 'localhost',
50
+ user: 'root', // 你的 MySQL 用户名
51
+ password: '123456', // 你的 MySQL 密码
52
+ database: 'my_test_db' // 数据库名
53
+
54
+ })
55
+
56
+
57
+ startServer({
58
+ port: 8008, // 端口配置
59
+ allowedOrigins: [ // 允许的域名
60
+ 'http://127.0.0.1:5501',
61
+ 'http://ztgame.click',
62
+ 'http://60.205.158.63',
63
+ 'http://localhost:5173'
64
+ ]
65
+ });
66
+
67
+
68
+ DefineRoutePlus_A({
69
+
70
+ /**
71
+ * 二次封装 defineRoute 函数
72
+ * {Object} options - 路由配置选项
73
+ * {string} options.url - 路由路径(必填)
74
+ * {string} options.method - HTTP 方法(GET/POST/PUT/DELETE,必填)
75
+ * {Array<Function>} [options.middlewares=[]] - 中间件数组(可选)
76
+ * {Function} options.handler - 业务逻辑处理函数(async (req) => data,必填)
77
+ * {Object} options.PlusHandler - 额外处理选项(必填)
78
+ * {Object} options.PlusHandler.db - 数据库操作选项(必填)
79
+ * {string} options.PlusHandler.db.table - 数据库表名(必填)
80
+ * {string} options.PlusHandler.db.operation - 数据库操作(必填)
81
+ * {string} [options.PlusHandler.db.primaryKey='id'] - 主键字段(可选)
82
+ * {string} [options.PlusHandler.db.fields='*'] - 查询字段(可选)
83
+ * {string} [options.PlusHandler.db.categoryField='category_id'] - 分类字段(可选)
84
+ * {Object} options.PlusHandler.Mode - 模式选项(必填)
85
+ * {boolean} [options.PlusHandler.Mode.pagination=false] - 是否支持分页(可选)
86
+ * {boolean} [options.PlusHandler.Mode.requireAuth=false] - 是否需要身份验证(可选)
87
+ * {boolean} [options.PlusHandler.Mode.shuffle=false] - 是否打乱数据(可选)
88
+ * {number} [options.PlusHandler.Mode.pageSize=10] - 每页大小(可选)
89
+ * {Object} options.PlusHandler.other - 其他选项(必填)
90
+ * {string} [options.PlusHandler.other.successMessage='操作成功'] - 成功消息(可选)
91
+ * {string} [options.PlusHandler.other.errorMessage='操作失败'] - 错误消息(可选)
92
+ * */
93
+
94
+
95
+ url: '/api/productlist',
96
+ //请求方法
97
+ method: 'get',
98
+ //内置方法
99
+ PlusHandler: {
100
+ //数据表操作
101
+ db: {
102
+ },
103
+ Mode: {
104
+ },
105
+ //其他
106
+ other: {
107
+ }
108
+ }
109
+
110
+ });
111
+
112
+
113
+ ```
114
+
115
+ ### 安装它
116
+ ```
117
+ npm install express-lowcode-by-ikun2274
118
+ ```
119
+
120
+
121
+
122
+ ### 其他
123
+
124
+ ```
125
+ 待迭代开发ing
126
+ ```
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "streamline-code-by-ikun2274",
3
+ "version": "0.11.1",
4
+ "description": "A streamline Express route builder with database operations, pagination, and authentication",
5
+ "main": "src/StreamlineCodeIndex.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./src/StreamlineCodeIndex.js",
9
+ "type": "./types/index.d.ts"
10
+
11
+ }
12
+ },
13
+ "scripts": {
14
+
15
+ },
16
+ "keywords": [
17
+ "express",
18
+ "router",
19
+ "streamline-code",
20
+ "database",
21
+ "pagination",
22
+ "authentication"
23
+ ],
24
+ "author": "ikun2274",
25
+ "license": "ISC",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/yourusername/express-route-builder.git"
29
+ },
30
+ "dependencies": {
31
+ "axios": "1.13.6",
32
+ "body-parser": "2.2.2",
33
+ "cors": "2.8.5",
34
+ "dotenv": "17.2.3",
35
+ "express": "5.1.0",
36
+ "fs-extra": "11.3.4",
37
+ "jsonwebtoken": "9.0.3",
38
+ "mysql2": "3.19.1"
39
+ }
40
+ }
@@ -0,0 +1 @@
1
+ export * from './data.js';
@@ -0,0 +1,161 @@
1
+
2
+
3
+ //data.js
4
+
5
+ import mysql from 'mysql2/promise';
6
+
7
+
8
+
9
+ // 数据库配置 模拟环境
10
+ /*
11
+ */
12
+
13
+
14
+ let dbConfig = {
15
+ host: 'localhost',
16
+ user: 'root', // 你的 MySQL 用户名
17
+ password: '123456', // 你的 MySQL 密码
18
+ database: 'my_test_db' // 数据库名
19
+ };
20
+
21
+ export function setDbConfig(config) {
22
+ dbConfig = { ...dbConfig, ...config };
23
+ }
24
+
25
+
26
+
27
+
28
+ // 数据库配置 生产环境 宝塔服务面板远程MySQL
29
+ /**
30
+
31
+
32
+ const dbConfig = {
33
+ host: '127.0.0.1', // 替换为完整的本地IP
34
+ user: 'Root',
35
+ password: 'mYGFXTY5iHkRbfJ8',
36
+ database: 'My_test_db'
37
+ };
38
+
39
+ */
40
+
41
+ export async function query(sql, params = []) {
42
+ const connection = await mysql.createConnection(dbConfig);
43
+ try {
44
+ const [rows] = await connection.execute(sql, params);
45
+ return rows;
46
+ } finally {
47
+ await connection.end();
48
+ }
49
+ }
50
+
51
+
52
+
53
+ // data.js(添加以下代码)
54
+ class DB {
55
+ /**
56
+ * 根据条件查询单条记录
57
+ * @param {string} table - 表名
58
+ * @param {object} where - 查询条件,如 { id: 1 }
59
+ * @param {string[]} fields - 要查询的字段,默认 ['*']
60
+ * @returns {object|null} 查询结果,无结果返回 null
61
+ */
62
+ async findOne(table, where = {}, fields = ['*']) {
63
+ const { sql, params } = this.buildSelectSQL(table, fields, where);
64
+ const [result] = await query(sql, params);
65
+ return result || null;
66
+ }
67
+
68
+ /**
69
+ * 查询多条记录
70
+ * @param {string} table - 表名
71
+ * @param {object} where - 查询条件,如 { age: { gt: 18 } }
72
+ * @param {string[]} fields - 要查询的字段,默认 ['*']
73
+ * @param {object} options - 其他选项,如 { limit: 10, orderBy: 'id DESC' }
74
+ * @returns {array} 查询结果数组
75
+ */
76
+ async find(table, where = {}, fields = ['*'], options = {}) {
77
+ const { sql, params } = this.buildSelectSQL(table, fields, where, options);
78
+ return await query(sql, params);
79
+ }
80
+
81
+ /**
82
+ * 插入记录
83
+ * @param {string} table - 表名
84
+ * @param {object} data - 要插入的数据,如 { name: '张三', age: 20 }
85
+ * @returns {object} 插入结果,包含 insertId
86
+ */
87
+ async create(table, data) {
88
+ const keys = Object.keys(data);
89
+ const values = Object.values(data);
90
+ const placeholders = keys.map(() => '?').join(', ');
91
+ const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;
92
+ const result = await query(sql, values);
93
+
94
+ return { ...data, id: result.insertId || null };
95
+ }
96
+
97
+ /**
98
+ * 更新记录
99
+ * @param {string} table - 表名
100
+ * @param {object} data - 要更新的数据,如 { name: '李四' }
101
+ * @param {object} where - 更新条件,如 { id: 1 }
102
+ * @returns {boolean} 是否更新成功
103
+ */
104
+ async update(table, data, where) {
105
+ const setClause = Object.keys(data).map(key => `${key} = ?`).join(', ');
106
+ const values = [...Object.values(data), ...Object.values(where)];
107
+ const whereClause = Object.keys(where).map(key => `${key} = ?`).join(' AND ');
108
+ const sql = `UPDATE ${table} SET ${setClause} WHERE ${whereClause}`;
109
+ const [result] = await query(sql, values);
110
+ return result.affectedRows > 0;
111
+ }
112
+
113
+ /**
114
+ * 删除记录
115
+ * @param {string} table - 表名
116
+ * @param {object} where - 删除条件,如 { id: 1 }
117
+ * @returns {boolean} 是否删除成功
118
+ */
119
+ async delete(table, where) {
120
+ const whereClause = Object.keys(where).map(key => `${key} = ?`).join(' AND ');
121
+ const sql = `DELETE FROM ${table} WHERE ${whereClause}`;
122
+ const [result] = await query(sql, Object.values(where));
123
+ return result.affectedRows > 0;
124
+ }
125
+
126
+ // 构建 SELECT SQL 语句的辅助方法
127
+ buildSelectSQL(table, fields, where, options = {}) {
128
+ const fieldStr = fields.join(', ');
129
+ let sql = `SELECT ${fieldStr} FROM ${table}`;
130
+ const params = [];
131
+
132
+ // 处理 WHERE 条件
133
+ if (Object.keys(where).length > 0) {
134
+ const conditions = [];
135
+ for (const [key, value] of Object.entries(where)) {
136
+ conditions.push(`${key} = ?`);
137
+ params.push(value);
138
+ }
139
+ sql += ` WHERE ${conditions.join(' AND ')}`;
140
+ }
141
+
142
+ // 处理排序
143
+ if (options.orderBy) {
144
+ sql += ` ORDER BY ${options.orderBy}`;
145
+ }
146
+
147
+ // 处理分页
148
+ if (options.limit) {
149
+ sql += ` LIMIT ?`;
150
+ params.push(options.limit);
151
+ if (options.offset) {
152
+ sql += ` OFFSET ?`;
153
+ params.push(options.offset);
154
+ }
155
+ }
156
+
157
+ return { sql, params };
158
+ }
159
+ }
160
+
161
+ export const ToolDb = new DB();
@@ -0,0 +1,3 @@
1
+ export * from './auth/AuthIndex.js';
2
+ export * from './data/DataIndex.js';
3
+ export * from './response/ResponseIndex.js';
@@ -0,0 +1,4 @@
1
+
2
+
3
+ export * from './token.js';
4
+ export * from './validation.js';
@@ -0,0 +1,27 @@
1
+ import { JWT_SECRET, TOKEN_EXPIRES_IN } from '../../Other/constant.js';
2
+ import jwt from 'jsonwebtoken';
3
+
4
+ export const generateToken = (req, res, next) => {
5
+ const { user } = req;
6
+
7
+ const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: TOKEN_EXPIRES_IN });
8
+
9
+ // 将 token 存储到请求对象中,供后续中间件使用
10
+ req.token = token;
11
+ next();
12
+ };
13
+
14
+ export const verifyToken = (req, res, next) => {
15
+ const authHeader = req.headers.authorization;
16
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
17
+ return res.status(401).json({ code: 401, message: '请先登录(未提供 token)' });
18
+ }
19
+ const token = authHeader.split(' ')[1];
20
+ try {
21
+ const decoded = jwt.verify(token, JWT_SECRET);
22
+ req.user = decoded;
23
+ next();
24
+ } catch (err) {
25
+ return res.status(401).json({ code: 401, message: 'token 无效或已过期,请重新登录' });
26
+ }
27
+ };
@@ -0,0 +1,60 @@
1
+ import { ToolDb } from '../../Databaseope/data.js';
2
+
3
+ export const validateLogin = (req, res, next) => {
4
+ const { username, password } = req.body;
5
+
6
+ if (!username || !password) {
7
+ return res.status(400).json({ code: 400, message: '用户名和密码不能为空' });
8
+ }
9
+
10
+ next();
11
+ };
12
+
13
+ export const validateRegister = (req, res, next) => {
14
+ const { username, password } = req.body;
15
+
16
+ // 校验用户名
17
+ if (!username) {
18
+ return res.status(400).json({ code: 400, Usermessage: '用户名不能为空喵~' });
19
+ }
20
+ if (username.length > 10) {
21
+ return res.status(400).json({ code: 400, Usermessage: '用户名不能超过10个字符喵~' });
22
+ }
23
+
24
+ // 校验密码
25
+ const passwordReg = /^\d{4,8}$/;
26
+ if (!password) {
27
+ return res.status(400).json({ code: 400, Passwordmessage: '密码不能为空喵~' });
28
+ }
29
+ if (!passwordReg.test(password)) {
30
+ return res.status(400).json({ code: 400, Passwordmessage: '密码必须是4-8位数字组成喵~' });
31
+ }
32
+
33
+ next();
34
+ };
35
+
36
+ export const checkUsername = async (req, res, next) => {
37
+ const { username } = req.body;
38
+
39
+ const exist = await ToolDb.findOne('users', { username });
40
+ if (exist) {
41
+ return res.status(400).json({ code: 400, Usermessage: '用户名已存在喵~' });
42
+ }
43
+
44
+ next();
45
+ };
46
+
47
+ export const verifyUser = async (req, res, next) => {
48
+ const { username, password } = req.body;
49
+
50
+ const user = await ToolDb.findOne('users', { username, password },
51
+ ['id', 'username', 'password']);
52
+
53
+ if (!user) {
54
+ return res.status(401).json({ code: 401, message: '账号或密码错误' });
55
+ }
56
+
57
+ // 将用户信息存储到请求对象中,供后续中间件使用
58
+ req.user = user;
59
+ next();
60
+ };
@@ -0,0 +1,3 @@
1
+ export * from './filter.js';
2
+ export * from './pagination.js';
3
+ export * from './utils.js';
@@ -0,0 +1,13 @@
1
+ export const categoryFilter = (categoryField = 'category_id') => (req, res, next) => {
2
+ // 构建查询条件
3
+ const where = {};
4
+ // 检查是否有分类ID
5
+ const categoryId = req.query.categoryId;
6
+ if (categoryId) {
7
+ where[categoryField] = categoryId;
8
+ }
9
+
10
+ // 将查询条件添加到请求对象中
11
+ req.query.where = where;
12
+ next();
13
+ };
@@ -0,0 +1,10 @@
1
+ export const Dpagination = (defaultPageSize = 10) => (req, res, next) => {
2
+ // 解析分页参数
3
+ const page = parseInt(req.query.page) || 1;
4
+ const pageSize = parseInt(req.query.pageSize) || defaultPageSize;
5
+ const offset = (page - 1) * pageSize;
6
+
7
+ // 将分页参数添加到请求对象中
8
+ req.pagination = { page, pageSize, offset };
9
+ next();
10
+ };
@@ -0,0 +1,33 @@
1
+ export const shuffleData = (req, res, next) => {
2
+ // Fisher-Yates 洗牌算法
3
+ function shuffleArray(array) {
4
+ for (let i = array.length - 1; i > 0; i--) {
5
+ const j = Math.floor(Math.random() * (i + 1));
6
+ [array[i], array[j]] = [array[j], array[i]];
7
+ }
8
+ return array;
9
+ }
10
+
11
+ // 将洗牌函数添加到请求对象中
12
+ req.shuffleArray = shuffleArray;
13
+ next();
14
+ };
15
+
16
+ export const generateId = (table, primaryKey = 'id') => async (req, res, next) => {
17
+ try {
18
+ const ToolDb = req.db || require('../../Databaseope/data.js').ToolDb;
19
+ // 生成新 id
20
+ const records = await ToolDb.find(table);
21
+ const ids = Array.isArray(records)
22
+ ? records.map(record => record[primaryKey]).filter(id => id !== null && id !== undefined && typeof id === 'number')
23
+ : [];
24
+ const maxId = ids.length > 0 ? Math.max(...ids) : 0;
25
+ const newId = maxId + 1;
26
+
27
+ // 将生成的ID添加到请求体中
28
+ req.body = { [primaryKey]: newId, ...req.body };
29
+ next();
30
+ } catch (error) {
31
+ next(error);
32
+ }
33
+ };
@@ -0,0 +1,21 @@
1
+ export const unifiedResponse = (successMessage = '操作成功') => (req, res, next) => {
2
+ // 保存原始的json方法
3
+ const originalJson = res.json;
4
+
5
+ // 重写json方法
6
+ res.json = function(data) {
7
+ // 如果数据已经是标准格式,直接返回
8
+ if (data.code !== undefined) {
9
+ return originalJson.call(this, data);
10
+ }
11
+
12
+ // 否则,包装为标准格式
13
+ return originalJson.call(this, {
14
+ code: 200,
15
+ data: data,
16
+ message: successMessage
17
+ });
18
+ };
19
+
20
+ next();
21
+ };
@@ -0,0 +1 @@
1
+ export * from './constant.js';
@@ -0,0 +1,4 @@
1
+ export const JWT_SECRET = 'your_very_secure_secret_key_123'; // 替换成随机复杂字符串
2
+ export const TOKEN_EXPIRES_IN = 60 * 60 * 24 * 14; // 60秒×60分×24小时×14天
3
+
4
+
@@ -0,0 +1 @@
1
+ export * from './StreamlineCode.js';
@@ -0,0 +1,308 @@
1
+ import express from 'express';
2
+ const app = express();
3
+ import { ToolDb } from '../Databaseope/data.js';
4
+ import {
5
+ validateLogin, verifyUser, generateToken,
6
+ validateRegister, checkUsername, verifyToken, categoryFilter, Dpagination, shuffleData, unifiedResponse
7
+ } from '../Middleware/MiddleWareIndex.js';
8
+
9
+
10
+ /**
11
+ * 二次封装 Express 路由注册
12
+ * @param {Object} options
13
+ * @param {string} options.url - 路由路径(必填)
14
+ * @param {string} options.method - HTTP 方法(GET/POST/PUT/DELETE,必填)
15
+ * @param {Array<Function>} [options.middlewares=[]] - 中间件数组(可选)
16
+ * @param {Function} options.handler - 业务逻辑处理函数(async (req) => data,必填)
17
+ */
18
+
19
+ export const defineRoute = (options) => {
20
+
21
+ const { url, method, middlewares = [], handler } = options;
22
+
23
+ // 校验参数(同上)
24
+ if (!url || !method || typeof handler !== 'function') {
25
+ throw new Error('url、method、handler 为必填项');
26
+ }
27
+
28
+ const httpMethod = method.toLowerCase();
29
+ const validMethods = ['get', 'post', 'put', 'delete'];
30
+ if (!validMethods.includes(httpMethod)) {
31
+ throw new Error(`不支持的方法:${method}`);
32
+ }
33
+
34
+ // 包装 handler:支持手动响应 + 自动兜底
35
+ const wrappedHandler = async (req, res, next) => {
36
+ try {
37
+ // 关键修改:让 handler 同时接收 req 和 res
38
+ const data = await handler(req, res);
39
+
40
+ // 如果没手动调用 res.json()/res.send() 等,就自动包装响应
41
+ if (!res.headersSent) {
42
+ res.status(200).json({
43
+ data: data || null // 用你想要的默认格式(比如 { data: ... })
44
+ });
45
+ }
46
+ } catch (err) {
47
+ // 错误处理:如果没手动响应错误,就自动处理
48
+ if (!res.headersSent) {
49
+ const status = err.status || 500;
50
+ res.status(status).json({
51
+ message: err.message || '服务器错误',
52
+ error: err.message
53
+ });
54
+ }
55
+ }
56
+ };
57
+
58
+ // 注册路由
59
+ app[httpMethod](url, ...middlewares, wrappedHandler);
60
+ };
61
+
62
+
63
+
64
+ /**
65
+ * 二次封装 defineRoute 函数
66
+ * @param {Object} options - 路由配置选项
67
+ * @param {string} options.url - 路由路径(必填)
68
+ * @param {string} options.method - HTTP 方法(GET/POST/PUT/DELETE,必填)
69
+ * @param {Array<Function>} [options.middlewares=[]] - 中间件数组(可选)//看你需求 因为我尽可能集成中间件了
70
+ * @param {Object} options.PlusHandler - 额外处理选项(必填)
71
+ * @param {Object} options.PlusHandler.db - 数据库操作(必填)
72
+ * @param {string} options.PlusHandler.db.table - 数据库表名(必填)
73
+ * @param {string} options.PlusHandler.db.operation - 数据表操作(必填)select/insert/update/update/delete
74
+ * @param {string} [options.PlusHandler.db.primaryKey='id'] - 主键字段(可选)
75
+ * @param {string} [options.PlusHandler.db.fields='*'] - 查询字段(可选)
76
+ * @param {string} [options.PlusHandler.db.categoryField='category_id'] - 分类字段(可选)
77
+ * @param {Object} options.PlusHandler.Mode - 模式选项(必填)
78
+ * @param {boolean} [options.PlusHandler.Mode.pagination=false] - 是否支持分页(可选)
79
+ * @param {boolean} [options.PlusHandler.Mode.requireAuth=false] - 是否需要身份验证(可选)
80
+ * @param {boolean} [options.PlusHandler.Mode.shuffle=false] - 是否打乱数据(可选)
81
+ * @param {number} [options.PlusHandler.Mode.pageSize=10] - 每页大小(可选)
82
+ * @param {Object} options.PlusHandler.other - 其他选项(必填)
83
+ * @param {string} [options.PlusHandler.other.successMessage='操作成功'] - 成功消息(可选)
84
+ * @param {string} [options.PlusHandler.other.errorMessage='操作失败'] - 错误消息(可选)
85
+ * */
86
+
87
+ export function DefineRoutePlus_A(options) {
88
+
89
+ const {
90
+ url,
91
+ method = 'get',
92
+ middlewares = [],
93
+
94
+ BuiltinMid = {
95
+ Parameter: '' || ['', ''],
96
+ },
97
+
98
+
99
+ PlusHandler: {
100
+ db: {
101
+ table,
102
+ operation,
103
+ primaryKey = 'id',
104
+ fields = '*',
105
+ categoryField = 'category_id',
106
+
107
+ },
108
+ /**
109
+ * Mode: {
110
+ pagination = false, // 是否支持分页
111
+ requireAuth = false, // 是否需要身份验证
112
+ validationMode = '', // 验证模式:login, register
113
+ shuffle = false, // 是否打乱数据
114
+ autoGenerateId = false, // 是否自动生成ID
115
+ pageSize = 10, // 每页大小
116
+ },
117
+
118
+ *
119
+ */
120
+
121
+ other: {
122
+ customLogic = null, // 自定义逻辑函数
123
+ successMessage = '操作成功', // 成功消息
124
+ errorMessage = '操作失败', // 错误消息
125
+ }
126
+
127
+ }
128
+ } = options
129
+
130
+ // 中间件映射表
131
+ const middlewareMap = {
132
+ 'requireAuth': () => verifyToken,
133
+ 'login': () => [validateLogin, verifyUser, generateToken],
134
+ 'register': () => [validateRegister, checkUsername],
135
+ 'categoryFilter': (field = categoryField) => categoryFilter(field),
136
+ 'pagination': (size = 10) => Dpagination(Number(size)),
137
+ 'shuffle': () => shuffleData,
138
+ 'unifiedResponse': (message = successMessage) => unifiedResponse(message)
139
+ };
140
+
141
+ // 构建中间件链
142
+ const builtInMiddlewares = [];
143
+
144
+ // 处理 BuiltinMid.Parameter
145
+ const parameters = Array.isArray(BuiltinMid.Parameter) ? BuiltinMid.Parameter : (BuiltinMid.Parameter ? [BuiltinMid.Parameter] : []);
146
+
147
+ for (const param of parameters) {
148
+ // 使用正则表达式匹配中间件名称和参数,格式:middleware:param1:param2
149
+ const match = param.match(/^([a-zA-Z0-9]+)(?::([^:]+))*$/);
150
+ if (match) {
151
+ const [, name, ...params] = match;
152
+ if (middlewareMap[name]) {
153
+ const middleware = middlewareMap[name](...params);
154
+ // 处理返回数组的中间件(如 login, register)
155
+ if (Array.isArray(middleware)) {
156
+ builtInMiddlewares.push(...middleware);
157
+ } else {
158
+ builtInMiddlewares.push(middleware);
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ // 默认添加分类过滤和统一响应中间件
165
+ if (!parameters.some(param => param.startsWith('categoryFilter'))) {
166
+ builtInMiddlewares.push(categoryFilter(categoryField));
167
+ }
168
+ if (!parameters.some(param => param.startsWith('unifiedResponse'))) {
169
+ builtInMiddlewares.push(unifiedResponse(successMessage));
170
+ }
171
+
172
+
173
+
174
+
175
+ // 合并用户自定义中间件
176
+ const finalMiddlewares = [...builtInMiddlewares, ...middlewares];
177
+
178
+ const defaultHandler = async (req, res) => {
179
+ try {
180
+ let result;
181
+
182
+ // 如果有自定义逻辑,执行自定义逻辑
183
+ if (customLogic && typeof customLogic === 'function') {
184
+ // 将successMessage和errorMessage作为参数传递给customLogic
185
+ result = await customLogic(req, res, ToolDb, successMessage, errorMessage);
186
+ // 如果自定义逻辑已经发送了响应,直接返回
187
+ if (res.headersSent) {
188
+ return;
189
+ }
190
+ } else {
191
+ // 根据操作类型执行数据库操作
192
+ switch (operation) {
193
+
194
+ case 'create':
195
+ // 处理创建操作
196
+ let createData = req.body;
197
+
198
+ // 如果需要自动生成ID
199
+ if (autoGenerateId) {
200
+ // 直接使用generateId中间件的逻辑
201
+ const records = await ToolDb.find(table);
202
+ const ids = Array.isArray(records)
203
+ ? records.map(record => record[primaryKey])
204
+ .filter(id => id !== null && id !== undefined && typeof id === 'number')
205
+ : [];
206
+ const maxId = ids.length > 0 ? Math.max(...ids) : 0;
207
+ const newId = maxId + 1;
208
+ createData = { [primaryKey]: newId, ...createData };
209
+ }
210
+
211
+ await ToolDb.create(table, createData);
212
+ break;
213
+
214
+ case 'select':
215
+ case 'read':
216
+ // 处理查询操作
217
+ // 从请求对象中获取查询条件(由categoryFilter中间件设置)
218
+ const where = req.query.where || {};
219
+
220
+ if (pagination) {
221
+ // 从请求对象中获取分页参数(由pagination中间件设置)
222
+ const { page, pageSize: size, offset } = req.pagination;
223
+
224
+ const fieldsArray = fields === '' ? ['*'] : fields.split(',');
225
+
226
+ let data = await ToolDb.find(table, where, fieldsArray, {
227
+ limit: size,
228
+ offset: offset
229
+ });
230
+
231
+ // 如果需要打乱数据
232
+ if (shuffle && req.shuffleArray) {
233
+ data = req.shuffleArray(data);
234
+ }
235
+
236
+ // 查询总数
237
+ const totalData = await ToolDb.find(table, where);
238
+ const total = totalData.length;
239
+ const totalPages = Math.ceil(total / size);
240
+
241
+ result = { data, pagination: { page, pageSize: size, total, totalPages } };
242
+ } else {
243
+ // 普通查询
244
+ const id = req.params[primaryKey];
245
+ if (id) {
246
+ // 根据 ID 查询
247
+ result = await ToolDb.findOne(table,
248
+ { [primaryKey]: id }, fields.split(','));
249
+ } else {
250
+ // 查询所有
251
+ let data = await ToolDb.find(table, where, fields.split(','));
252
+ // 如果需要打乱数据
253
+ if (shuffle && req.shuffleArray) {
254
+ data = req.shuffleArray(data);
255
+ }
256
+ result = data;
257
+ }
258
+ }
259
+ break;
260
+
261
+ case 'update':
262
+ // 处理更新操作
263
+ const id = req.params[primaryKey];
264
+ const updateData = req.body;
265
+ await ToolDb.update(table, updateData, { [primaryKey]: id });
266
+ result = { message: successMessage };
267
+ break;
268
+
269
+ case 'delete':
270
+ // 处理删除操作
271
+ const deleteId = req.params[primaryKey];
272
+ await ToolDb.delete(table, { [primaryKey]: deleteId });
273
+ result = { message: successMessage };
274
+ break;
275
+
276
+
277
+
278
+
279
+
280
+
281
+ default:
282
+ throw new Error('不支持的操作类型');
283
+ }
284
+ }
285
+
286
+ // 统一响应格式
287
+ res.json({ code: 200, data: result, message: successMessage });
288
+ } catch (error) {
289
+ // 统一错误处理
290
+ res.status(500).json({ code: 500, message: errorMessage, error: error.message });
291
+ }
292
+ };
293
+
294
+ defineRoute({
295
+ url,
296
+ method,
297
+ middlewares: finalMiddlewares,
298
+ handler: defaultHandler // 传递封装后的 handler
299
+ });
300
+
301
+ }
302
+
303
+
304
+
305
+
306
+
307
+ // 导出 app 实例(用于启动服务)
308
+ export default app;
@@ -0,0 +1,5 @@
1
+ export * from './Databaseope/DataIndex.js';
2
+ export * from './Middleware/MiddleWareIndex.js'
3
+ export * from './Tool/ToolIndex.js'
4
+ export * from './Request/RequestIndex.js';
5
+ export * from './Other/OtherIndex.js';
@@ -0,0 +1 @@
1
+ export * from './server.js';
@@ -0,0 +1,43 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import app from "../Request/StreamlineCode.js";
4
+
5
+ /**
6
+ * 启动服务器
7
+ * @param {Object} options - 配置选项
8
+ * @param {number} options.port - 服务器端口,默认3001
9
+ * @param {string[]} options.allowedOrigins - 允许的域名列表
10
+ */
11
+ export function startServer(options = {}) {
12
+ const {
13
+ port = 3001,
14
+ allowedOrigins = [
15
+ 'http://127.0.0.1:5501',
16
+ ]
17
+ } = options;
18
+
19
+ // 配置CORS
20
+ app.use(cors({
21
+ // 核心:白名单判断,只放行指定的域名
22
+ origin: (origin, callback) => {
23
+ // 允许白名单内的地址,或本地调试(origin为null的情况)
24
+ if (!origin || allowedOrigins.includes(origin)) {
25
+ callback(null, origin || '*'); // 放行
26
+ } else {
27
+ callback(null, false);
28
+ }
29
+ },
30
+ credentials: true, // 保留Cookie支持
31
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
32
+ allowedHeaders: ['Content-Type', 'Authorization']
33
+ }));
34
+
35
+ // 配置中间件
36
+ app.use(express.json());
37
+ app.use(express.static('public'));
38
+
39
+ // 启动服务器
40
+ app.listen(port, () => {
41
+ console.log(`后端服务运行在 http://localhost:${port}`);
42
+ });
43
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * express-lowcode-by-ikun2274 - 低代码 Express 路由构建器
3
+ * 提供数据库操作、分页、身份验证等功能
4
+ */
5
+ declare module "express-lowcode-by-ikun2274" {
6
+ /**
7
+ * 数据库配置接口
8
+ */
9
+ export interface DbConfig {
10
+ /** 数据库主机地址 */
11
+ host: string;
12
+ /** 数据库用户名 */
13
+ user: string;
14
+ /** 数据库密码 */
15
+ password: string;
16
+ /** 数据库名称 */
17
+ database: string;
18
+ }
19
+
20
+ /**
21
+ * 服务器配置接口
22
+ */
23
+ export interface ServerConfig {
24
+ /** 服务器端口 */
25
+ port: number;
26
+ /** 允许的跨域域名列表 */
27
+ allowedOrigins: string[];
28
+ }
29
+
30
+ /**
31
+ * 数据库操作配置接口
32
+ */
33
+ export interface PlusHandlerDb {
34
+ /** 数据库表名 */
35
+ table: string;
36
+ /** 操作类型 */
37
+ operation: "read" | "create" | "update" | "delete";
38
+ /** 主键字段名,默认为 'id' */
39
+ primaryKey?: string;
40
+ /** 查询字段,默认为 '*' */
41
+ fields?: string;
42
+ /** 分类字段名,默认为 'category_id' */
43
+ categoryField?: string;
44
+ /** 其他配置 */
45
+ [key: string]: any;
46
+ }
47
+
48
+ /**
49
+ * 模式配置接口
50
+ */
51
+ export interface PlusHandlerMode {
52
+ /** 是否支持分页,默认为 false */
53
+ pagination?: boolean;
54
+ /** 是否需要身份验证,默认为 false */
55
+ requireAuth?: boolean;
56
+ /** 验证模式,可选 'login' 或 'register' */
57
+ validationMode?: string;
58
+ /** 是否打乱数据,默认为 false */
59
+ shuffle?: boolean;
60
+ /** 是否自动生成 ID,默认为 false */
61
+ autoGenerateId?: boolean;
62
+ /** 每页大小,默认为 10 */
63
+ pageSize?: number;
64
+ /** 其他配置 */
65
+ [key: string]: any;
66
+ }
67
+
68
+ /**
69
+ * 其他配置接口
70
+ */
71
+ export interface PlusHandlerOther {
72
+ /** 成功消息,默认为 '操作成功' */
73
+ successMessage?: string;
74
+ /** 错误消息,默认为 '操作失败' */
75
+ errorMessage?: string;
76
+ /** 自定义逻辑函数 */
77
+ customLogic?: (
78
+ req: any,
79
+ res: any,
80
+ ToolDb: any,
81
+ successMessage: string,
82
+ errorMessage: string,
83
+ ) => Promise<any>;
84
+ /** 其他配置 */
85
+ [key: string]: any;
86
+ }
87
+
88
+ /**
89
+ * 内置处理器配置接口
90
+ */
91
+ export interface PlusHandler {
92
+ /** 数据库操作配置 */
93
+ db: PlusHandlerDb;
94
+ /** 模式配置 */
95
+ Mode: PlusHandlerMode;
96
+ /** 其他配置 */
97
+ other?: PlusHandlerOther;
98
+ }
99
+
100
+ /**
101
+ * 路由配置接口
102
+ */
103
+ export interface RouteConfig {
104
+ /** 路由路径 */
105
+ url: string;
106
+ /** HTTP 方法 */
107
+ method: "get" | "post" | "put" | "delete";
108
+ /** 中间件数组(可选)//看你需求 因为我尽可能集成中间件了 */
109
+ middlewares?: Array<(req: any, res: any, next: () => void) => void>;
110
+ /** 内置处理器配置 */
111
+ PlusHandler: PlusHandler;
112
+ /** 其他配置 */
113
+ [key: string]: any;
114
+ }
115
+
116
+ /**
117
+ * 配置数据库连接
118
+ * @param config 数据库配置
119
+ *
120
+ */
121
+ export function setDbConfig(config: DbConfig): void;
122
+
123
+ /**
124
+ * 启动服务器
125
+ * @param config 服务器配置
126
+ */
127
+ export function startServer(config: ServerConfig): void;
128
+
129
+ /**
130
+ * 定义增强路由
131
+ * @param config 路由配置
132
+ * @param {Object} options - 路由配置选项
133
+ * @param {string} options.url - 路由路径(必填)
134
+ * @param {string} options.method - HTTP 方法(GET/POST/PUT/DELETE,必填)
135
+ *
136
+ * @param {Array<Function>} [options.middlewares=[]] - 中间件数组(可选)//看你需求 因为我尽可能集成中间件了
137
+ * @param {Object} options.PlusHandler - 额外处理选项(必填)
138
+ * @param {Object} options.PlusHandler.db - 数据库操作(必填)
139
+ * @param {string} options.PlusHandler.db.table - 数据库表名(必填)
140
+ * @param {string} options.PlusHandler.db.operation - 数据表操作(必填)select/insert/update/update/delete
141
+ * @param {string} [options.PlusHandler.db.primaryKey='id'] - 主键字段(可选)
142
+ * @param {string} [options.PlusHandler.db.fields='*'] - 查询字段(可选)
143
+ * @param {string} [options.PlusHandler.db.categoryField='category_id'] - 分类字段(可选)
144
+ * @param {Object} options.PlusHandler.Mode - 模式选项(必填)
145
+ * @param {boolean} [options.PlusHandler.Mode.pagination=false] - 是否支持分页(可选)
146
+ * @param {boolean} [options.PlusHandler.Mode.requireAuth=false] - 是否需要身份验证(可选)
147
+ * @param {boolean} [options.PlusHandler.Mode.shuffle=false] - 是否打乱数据(可选)
148
+ * @param {number} [options.PlusHandler.Mode.pageSize=10] - 每页大小(可选)
149
+ * @param {Object} options.PlusHandler.other - 其他选项(必填)
150
+ * @param {string} [options.PlusHandler.other.successMessage='操作成功'] - 成功消息(可选)
151
+ * @param {string} [options.PlusHandler.other.errorMessage='操作失败'] - 错误消息(可选)
152
+ */
153
+ export function DefineRoutePlus_A(config: RouteConfig): void;
154
+ }