befly-tpl 3.10.46 → 3.10.48
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 +24 -25
- package/apis/test/hi.ts +11 -3
- package/main.ts +1 -1
- package/package.json +21 -22
- package/pm2.config.cjs +7 -7
- package/tsconfig.json +3 -2
- package/apis/test/typedExample.ts +0 -149
- package/tests/fields-exclude.test.ts +0 -136
package/README.md
CHANGED
|
@@ -37,10 +37,10 @@ bunx befly init
|
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
39
|
// main.ts
|
|
40
|
-
import { Befly } from
|
|
40
|
+
import { Befly } from "befly";
|
|
41
41
|
|
|
42
42
|
const app = new Befly({
|
|
43
|
-
appName:
|
|
43
|
+
appName: "My API",
|
|
44
44
|
appPort: 3000
|
|
45
45
|
});
|
|
46
46
|
|
|
@@ -57,15 +57,15 @@ bun run main.ts
|
|
|
57
57
|
|
|
58
58
|
```typescript
|
|
59
59
|
// apis/user/hello.ts
|
|
60
|
-
import type { ApiRoute } from
|
|
60
|
+
import type { ApiRoute } from "befly/types/api";
|
|
61
61
|
|
|
62
62
|
export default {
|
|
63
|
-
name:
|
|
63
|
+
name: "问候接口",
|
|
64
64
|
auth: false, // 公开接口
|
|
65
65
|
fields: {},
|
|
66
66
|
handler: async (befly, ctx) => {
|
|
67
67
|
return {
|
|
68
|
-
msg:
|
|
68
|
+
msg: "Hello, Befly!",
|
|
69
69
|
data: {
|
|
70
70
|
timestamp: Date.now()
|
|
71
71
|
}
|
|
@@ -81,26 +81,27 @@ export default {
|
|
|
81
81
|
### TypeScript 全面支持
|
|
82
82
|
|
|
83
83
|
```typescript
|
|
84
|
-
import type { ApiRoute
|
|
85
|
-
import type {
|
|
84
|
+
import type { ApiRoute } from "befly/types/api";
|
|
85
|
+
import type { BeflyContext } from "befly/types/befly";
|
|
86
|
+
import type { User } from "./types/models";
|
|
86
87
|
|
|
87
88
|
export default {
|
|
88
|
-
name:
|
|
89
|
+
name: "获取用户",
|
|
89
90
|
auth: true,
|
|
90
91
|
fields: {
|
|
91
|
-
id:
|
|
92
|
+
id: "用户ID|number|1|999999|null|1|null"
|
|
92
93
|
},
|
|
93
|
-
required: [
|
|
94
|
+
required: ["id"],
|
|
94
95
|
handler: async (befly: BeflyContext, ctx) => {
|
|
95
96
|
const { id } = ctx.body;
|
|
96
97
|
|
|
97
98
|
// 类型安全的数据库查询
|
|
98
99
|
const user = await befly.db.getOne<User>({
|
|
99
|
-
table:
|
|
100
|
+
table: "user",
|
|
100
101
|
where: { id }
|
|
101
102
|
});
|
|
102
103
|
|
|
103
|
-
return { msg:
|
|
104
|
+
return { msg: "查询成功", data: user };
|
|
104
105
|
}
|
|
105
106
|
} as ApiRoute;
|
|
106
107
|
```
|
|
@@ -110,40 +111,40 @@ export default {
|
|
|
110
111
|
```typescript
|
|
111
112
|
// 查询单条
|
|
112
113
|
const user = await befly.db.getOne<User>({
|
|
113
|
-
table:
|
|
114
|
+
table: "user",
|
|
114
115
|
where: { id: 1 }
|
|
115
116
|
});
|
|
116
117
|
|
|
117
118
|
// 分页列表
|
|
118
119
|
const result = await befly.db.getList<Product>({
|
|
119
|
-
table:
|
|
120
|
-
where: { category:
|
|
120
|
+
table: "product",
|
|
121
|
+
where: { category: "electronics" },
|
|
121
122
|
page: 1,
|
|
122
123
|
limit: 10,
|
|
123
|
-
orderBy: [
|
|
124
|
+
orderBy: ["createdAt#DESC"]
|
|
124
125
|
});
|
|
125
126
|
|
|
126
127
|
// 插入数据
|
|
127
128
|
await befly.db.insData({
|
|
128
|
-
table:
|
|
129
|
+
table: "user",
|
|
129
130
|
data: {
|
|
130
|
-
username:
|
|
131
|
-
email:
|
|
131
|
+
username: "john",
|
|
132
|
+
email: "john@example.com"
|
|
132
133
|
}
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
// 更新数据
|
|
136
137
|
await befly.db.updData({
|
|
137
|
-
table:
|
|
138
|
+
table: "user",
|
|
138
139
|
where: { id: 1 },
|
|
139
140
|
data: {
|
|
140
|
-
nickname:
|
|
141
|
+
nickname: "John Doe"
|
|
141
142
|
}
|
|
142
143
|
});
|
|
143
144
|
|
|
144
145
|
// 删除数据
|
|
145
146
|
await befly.db.delData({
|
|
146
|
-
table:
|
|
147
|
+
table: "user",
|
|
147
148
|
where: { id: 1 }
|
|
148
149
|
});
|
|
149
150
|
```
|
|
@@ -164,9 +165,7 @@ await befly.db.delData({
|
|
|
164
165
|
|
|
165
166
|
同步到数据库:
|
|
166
167
|
|
|
167
|
-
|
|
168
|
-
bun run scripts/syncDb.ts
|
|
169
|
-
```
|
|
168
|
+
请参考:`befly` 的同步文档:`packages/core/docs/reference/sync.md`(`syncDb` / `syncAll` 等同步流程说明)。
|
|
170
169
|
|
|
171
170
|
## 🗄️ 数据库配置
|
|
172
171
|
|
package/apis/test/hi.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 示例 / 测试接口
|
|
3
|
+
*
|
|
4
|
+
* 注意:本文件仅用于模板演示与本地测试,不建议在生产环境启用或依赖其行为。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { BeflyContext } from "befly/types/befly";
|
|
8
|
+
|
|
1
9
|
export default {
|
|
2
|
-
name:
|
|
3
|
-
handler: async (befly
|
|
10
|
+
name: "测试接口",
|
|
11
|
+
handler: async (befly: BeflyContext) => {
|
|
4
12
|
// 返回成功信息
|
|
5
|
-
return befly.tool.Yes(
|
|
13
|
+
return befly.tool.Yes("测试成功");
|
|
6
14
|
}
|
|
7
15
|
};
|
package/main.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "befly-tpl",
|
|
3
|
-
"version": "3.10.
|
|
4
|
-
"description": "Befly 3.0 TypeScript Template",
|
|
3
|
+
"version": "3.10.48",
|
|
5
4
|
"private": false,
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"registry": "https://registry.npmjs.org"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"dev": "NODE_ENV=development bun run main.ts",
|
|
12
|
-
"start": "NODE_ENV=production bun run main.ts",
|
|
13
|
-
"pm2": "bun --bun pm2 start pm2.config.cjs",
|
|
14
|
-
"test": "bun test"
|
|
15
|
-
},
|
|
5
|
+
"description": "Befly 3.0 TypeScript Template",
|
|
6
|
+
"type": "module",
|
|
16
7
|
"files": [
|
|
17
|
-
"apis",
|
|
18
|
-
"tables",
|
|
19
|
-
"tests",
|
|
20
|
-
"main.ts",
|
|
21
8
|
".npmrc",
|
|
22
|
-
"bunfig.toml",
|
|
23
9
|
"LICENSE",
|
|
10
|
+
"README.md",
|
|
11
|
+
"apis",
|
|
12
|
+
"bunfig.toml",
|
|
24
13
|
"main.ts",
|
|
25
14
|
"package.json",
|
|
26
15
|
"pm2.config.cjs",
|
|
27
|
-
"
|
|
16
|
+
"tables",
|
|
17
|
+
"tests",
|
|
28
18
|
"tsconfig.json"
|
|
29
19
|
],
|
|
30
|
-
"
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "NODE_ENV=development bun run main.ts",
|
|
22
|
+
"start": "NODE_ENV=production bun run main.ts",
|
|
23
|
+
"pm2": "bun --bun pm2 start pm2.config.cjs",
|
|
24
|
+
"test": "bun test"
|
|
25
|
+
},
|
|
31
26
|
"dependencies": {
|
|
32
|
-
"@befly-addon/admin": "^1.1.
|
|
33
|
-
"befly": "^3.9.
|
|
27
|
+
"@befly-addon/admin": "^1.1.32",
|
|
28
|
+
"befly": "^3.9.40"
|
|
34
29
|
},
|
|
35
30
|
"engines": {
|
|
36
31
|
"bun": ">=1.3.0"
|
|
37
32
|
},
|
|
38
|
-
"
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"registry": "https://registry.npmjs.org"
|
|
36
|
+
},
|
|
37
|
+
"gitHead": "0ba53d2bbdc6a7f2659ef60256cda7302fe585b0"
|
|
39
38
|
}
|
package/pm2.config.cjs
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
apps: [
|
|
3
3
|
{
|
|
4
|
-
name:
|
|
5
|
-
script:
|
|
6
|
-
interpreter:
|
|
4
|
+
name: "befly",
|
|
5
|
+
script: "main.ts",
|
|
6
|
+
interpreter: "bun",
|
|
7
7
|
|
|
8
8
|
// 集群模式配置
|
|
9
9
|
instances: 2, // 实例数量,可设置为 'max' 使用所有 CPU
|
|
10
|
-
exec_mode:
|
|
10
|
+
exec_mode: "cluster", // 集群模式
|
|
11
11
|
|
|
12
12
|
// 自动重启配置
|
|
13
13
|
autorestart: true,
|
|
14
14
|
watch: false,
|
|
15
|
-
max_memory_restart:
|
|
15
|
+
max_memory_restart: "500M", // 内存超过 500M 自动重启
|
|
16
16
|
|
|
17
17
|
// 日志配置
|
|
18
|
-
log_date_format:
|
|
18
|
+
log_date_format: "YYYY-MM-DD HH:mm:ss",
|
|
19
19
|
merge_logs: true,
|
|
20
20
|
|
|
21
21
|
// 从 .env.production 动态加载的环境变量(使用 Bun API)
|
|
22
22
|
env: {
|
|
23
|
-
NODE_ENV:
|
|
23
|
+
NODE_ENV: "production"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
]
|
package/tsconfig.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
4
|
"target": "ESNext",
|
|
4
5
|
"module": "ESNext",
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
"noEmit": true,
|
|
9
10
|
"strict": true,
|
|
10
11
|
"skipLibCheck": true,
|
|
11
|
-
"types": ["bun
|
|
12
|
+
"types": ["bun"],
|
|
12
13
|
"baseUrl": ".",
|
|
13
14
|
"paths": {
|
|
14
15
|
"befly": ["../core/main.ts"],
|
|
@@ -19,5 +20,5 @@
|
|
|
19
20
|
"forceConsistentCasingInFileNames": true
|
|
20
21
|
},
|
|
21
22
|
"include": ["**/*.ts", "**/*.d.ts"],
|
|
22
|
-
"exclude": ["node_modules", "data", "logs"]
|
|
23
|
+
"exclude": ["node_modules", "data", "logs", "tests"]
|
|
23
24
|
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DbHelper 泛型类型使用示例
|
|
3
|
-
*
|
|
4
|
-
* 本文件演示如何使用类型安全的数据库操作
|
|
5
|
-
* 通过扩展 DatabaseTables 接口,可以获得完整的类型推断和智能提示
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { BaseTable, TypedWhereConditions } from 'befly/types/table';
|
|
9
|
-
|
|
10
|
-
// ============================================
|
|
11
|
-
// 步骤 1: 定义表类型
|
|
12
|
-
// ============================================
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 用户表类型定义
|
|
16
|
-
* 只需定义业务字段,系统字段(id, state, createdAt 等)由 BaseTable 自动添加
|
|
17
|
-
*/
|
|
18
|
-
interface UserFields {
|
|
19
|
-
email: string;
|
|
20
|
-
username: string;
|
|
21
|
-
password: string;
|
|
22
|
-
nickname: string | null;
|
|
23
|
-
avatar: string | null;
|
|
24
|
-
roleId: number;
|
|
25
|
-
lastLoginAt: number | null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 完整的用户表类型(包含系统字段)
|
|
30
|
-
*/
|
|
31
|
-
type UserTable = BaseTable<UserFields>;
|
|
32
|
-
|
|
33
|
-
// ============================================
|
|
34
|
-
// 步骤 2: 扩展 DatabaseTables(可选,推荐)
|
|
35
|
-
// ============================================
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 在项目的 types/index.d.ts 中添加以下声明:
|
|
39
|
-
*
|
|
40
|
-
* declare module 'befly/types/table' {
|
|
41
|
-
* interface DatabaseTables {
|
|
42
|
-
* user: BaseTable<{
|
|
43
|
-
* email: string;
|
|
44
|
-
* username: string;
|
|
45
|
-
* password: string;
|
|
46
|
-
* nickname: string | null;
|
|
47
|
-
* avatar: string | null;
|
|
48
|
-
* roleId: number;
|
|
49
|
-
* lastLoginAt: number | null;
|
|
50
|
-
* }>;
|
|
51
|
-
* }
|
|
52
|
-
* }
|
|
53
|
-
*
|
|
54
|
-
* 扩展后,db.getOne({ table: 'user' }) 的返回类型会自动推断
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
// ============================================
|
|
58
|
-
// 步骤 3: 在 API 中使用类型安全的数据库操作
|
|
59
|
-
// ============================================
|
|
60
|
-
|
|
61
|
-
export default {
|
|
62
|
-
name: '类型安全示例',
|
|
63
|
-
auth: false,
|
|
64
|
-
handler: async (befly, ctx) => {
|
|
65
|
-
// ----------------------------------------
|
|
66
|
-
// 示例 1: 类型安全的 WHERE 条件
|
|
67
|
-
// ----------------------------------------
|
|
68
|
-
|
|
69
|
-
// 定义类型安全的查询条件
|
|
70
|
-
const where: TypedWhereConditions<UserTable> = {
|
|
71
|
-
state: 1, // 精确匹配
|
|
72
|
-
roleId$in: [1, 2, 3], // IN 数组(必须是 number[])
|
|
73
|
-
email$like: '%@gmail.com', // LIKE 匹配(必须是 string)
|
|
74
|
-
lastLoginAt$gte: Date.now() - 86400000 // 大于等于(必须是 number)
|
|
75
|
-
// roleId$in: 'invalid', // ❌ 类型错误:应为 number[]
|
|
76
|
-
// email$like: 123, // ❌ 类型错误:应为 string
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// ----------------------------------------
|
|
80
|
-
// 示例 2: 使用泛型指定返回类型
|
|
81
|
-
// ----------------------------------------
|
|
82
|
-
|
|
83
|
-
// 方式 A: 手动指定泛型
|
|
84
|
-
const user = await befly.db.getOne<UserTable>({
|
|
85
|
-
table: 'user',
|
|
86
|
-
where: { id: ctx.body.id }
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
if (user) {
|
|
90
|
-
// 有完整的类型提示
|
|
91
|
-
const email = user.email; // string
|
|
92
|
-
const createdAt = user.createdAt; // number(系统字段)
|
|
93
|
-
const nickname = user.nickname; // string | null
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// ----------------------------------------
|
|
97
|
-
// 示例 3: 类型安全的列表查询
|
|
98
|
-
// ----------------------------------------
|
|
99
|
-
|
|
100
|
-
const result = await befly.db.getList<UserTable>({
|
|
101
|
-
table: 'user',
|
|
102
|
-
where: where,
|
|
103
|
-
orderBy: ['createdAt#DESC'],
|
|
104
|
-
page: 1,
|
|
105
|
-
limit: 10
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// result.lists 类型为 UserTable[]
|
|
109
|
-
for (const item of result.lists) {
|
|
110
|
-
// 完整的类型提示
|
|
111
|
-
console.log(item.email, item.createdAt);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// ----------------------------------------
|
|
115
|
-
// 示例 4: 复杂 WHERE 条件($or, $and)
|
|
116
|
-
// ----------------------------------------
|
|
117
|
-
|
|
118
|
-
const complexWhere: TypedWhereConditions<UserTable> = {
|
|
119
|
-
state: 1,
|
|
120
|
-
$or: [{ email$like: '%@gmail.com' }, { email$like: '%@qq.com' }],
|
|
121
|
-
$and: [{ roleId$in: [1, 2] }, { lastLoginAt$notNull: true }]
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const activeUsers = await befly.db.getAll<UserTable>({
|
|
125
|
-
table: 'user',
|
|
126
|
-
where: complexWhere,
|
|
127
|
-
orderBy: ['lastLoginAt#DESC']
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// ----------------------------------------
|
|
131
|
-
// 示例 5: BETWEEN 范围查询
|
|
132
|
-
// ----------------------------------------
|
|
133
|
-
|
|
134
|
-
const rangeWhere: TypedWhereConditions<UserTable> = {
|
|
135
|
-
state: 1,
|
|
136
|
-
createdAt$between: [
|
|
137
|
-
Date.now() - 7 * 86400000, // 7天前
|
|
138
|
-
Date.now() // 现在
|
|
139
|
-
],
|
|
140
|
-
roleId$between: [1, 10] // 角色 ID 1-10
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
return befly.tool.Yes('类型安全示例', {
|
|
144
|
-
user: user,
|
|
145
|
-
total: result.total,
|
|
146
|
-
activeCount: activeUsers.length
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
};
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 测试字段排除功能
|
|
3
|
-
* 验证 fields 的3种写法:空数组、全部包含、全部排除
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Befly } from 'befly';
|
|
7
|
-
|
|
8
|
-
async function testFieldsExclude() {
|
|
9
|
-
// 强制启用数据库
|
|
10
|
-
process.env.DATABASE_ENABLE = '1';
|
|
11
|
-
|
|
12
|
-
// 创建 Befly 实例
|
|
13
|
-
const befly = new Befly();
|
|
14
|
-
|
|
15
|
-
// 启动服务器(这会初始化所有插件包括数据库)
|
|
16
|
-
const server = await befly.start();
|
|
17
|
-
|
|
18
|
-
// 获取 db 实例
|
|
19
|
-
const db = befly.appContext.db;
|
|
20
|
-
const redis = befly.appContext.redis;
|
|
21
|
-
|
|
22
|
-
console.log('\n========== 测试开始 ==========\n');
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
// 测试1:空数组(查询所有字段)
|
|
26
|
-
console.log('【测试1】空数组 - 查询所有字段');
|
|
27
|
-
const result1 = await db.getOne({
|
|
28
|
-
table: 'addon_admin_user',
|
|
29
|
-
fields: [],
|
|
30
|
-
where: { id: 1 }
|
|
31
|
-
});
|
|
32
|
-
console.log('结果字段数:', Object.keys(result1 || {}).length);
|
|
33
|
-
console.log('字段列表:', Object.keys(result1 || {}).join(', '));
|
|
34
|
-
|
|
35
|
-
// 测试2:指定包含字段
|
|
36
|
-
console.log('\n【测试2】指定包含字段 - 只查询 id, name, email');
|
|
37
|
-
const result2 = await db.getOne({
|
|
38
|
-
table: 'addon_admin_user',
|
|
39
|
-
fields: ['id', 'name', 'email'],
|
|
40
|
-
where: { id: 1 }
|
|
41
|
-
});
|
|
42
|
-
console.log('结果字段数:', Object.keys(result2 || {}).length);
|
|
43
|
-
console.log('字段列表:', Object.keys(result2 || {}).join(', '));
|
|
44
|
-
|
|
45
|
-
// 测试3:排除字段(排除敏感字段)
|
|
46
|
-
console.log('\n【测试3】排除字段 - 排除 password, salt');
|
|
47
|
-
const result3 = await db.getOne({
|
|
48
|
-
table: 'addon_admin_user',
|
|
49
|
-
fields: ['!password', '!salt'],
|
|
50
|
-
where: { id: 1 }
|
|
51
|
-
});
|
|
52
|
-
console.log('结果字段数:', Object.keys(result3 || {}).length);
|
|
53
|
-
console.log('字段列表:', Object.keys(result3 || {}).join(', '));
|
|
54
|
-
console.log('是否包含 password:', 'password' in (result3 || {}));
|
|
55
|
-
console.log('是否包含 salt:', 'salt' in (result3 || {}));
|
|
56
|
-
|
|
57
|
-
// 测试4:getList 支持排除字段
|
|
58
|
-
console.log('\n【测试4】getList - 排除字段');
|
|
59
|
-
const result4 = await db.getList({
|
|
60
|
-
table: 'addon_admin_user',
|
|
61
|
-
fields: ['!password', '!salt'],
|
|
62
|
-
page: 1,
|
|
63
|
-
limit: 2
|
|
64
|
-
});
|
|
65
|
-
console.log('查询到记录数:', result4.lists.length);
|
|
66
|
-
if (result4.lists.length > 0) {
|
|
67
|
-
console.log('第一条记录字段:', Object.keys(result4.lists[0]).join(', '));
|
|
68
|
-
console.log('是否包含 password:', 'password' in result4.lists[0]);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 测试5:getAll 支持排除字段
|
|
72
|
-
console.log('\n【测试5】getAll - 排除字段');
|
|
73
|
-
const result5 = await db.getAll({
|
|
74
|
-
table: 'addon_admin_user',
|
|
75
|
-
fields: ['!password', '!salt']
|
|
76
|
-
});
|
|
77
|
-
console.log('查询到记录数:', result5.length);
|
|
78
|
-
if (result5.length > 0) {
|
|
79
|
-
console.log('第一条记录字段:', Object.keys(result5[0]).join(', '));
|
|
80
|
-
console.log('是否包含 password:', 'password' in result5[0]);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 测试6:混用检测(应该报错)
|
|
84
|
-
console.log('\n【测试6】混用检测 - 应该抛出错误');
|
|
85
|
-
try {
|
|
86
|
-
await db.getOne({
|
|
87
|
-
table: 'addon_admin_user',
|
|
88
|
-
fields: ['id', '!password'],
|
|
89
|
-
where: { id: 1 }
|
|
90
|
-
});
|
|
91
|
-
console.log('❌ 没有抛出错误(不符合预期)');
|
|
92
|
-
} catch (error: any) {
|
|
93
|
-
console.log('✅ 成功捕获错误:', error.message);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// 测试7:星号检测(应该报错)
|
|
97
|
-
console.log('\n【测试7】星号检测 - 应该抛出错误');
|
|
98
|
-
try {
|
|
99
|
-
await db.getOne({
|
|
100
|
-
table: 'addon_admin_user',
|
|
101
|
-
fields: ['*'],
|
|
102
|
-
where: { id: 1 }
|
|
103
|
-
});
|
|
104
|
-
console.log('❌ 没有抛出错误(不符合预期)');
|
|
105
|
-
} catch (error: any) {
|
|
106
|
-
console.log('✅ 成功捕获错误:', error.message);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// 测试8:缓存性能测试
|
|
110
|
-
console.log('\n【测试8】缓存性能测试 - 多次查询相同表');
|
|
111
|
-
const start = Date.now();
|
|
112
|
-
for (let i = 0; i < 5; i++) {
|
|
113
|
-
await db.getOne({
|
|
114
|
-
table: 'addon_admin_user',
|
|
115
|
-
fields: ['!password', '!salt'],
|
|
116
|
-
where: { id: 1 }
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
const duration = Date.now() - start;
|
|
120
|
-
console.log(`5次查询总耗时: ${duration}ms`);
|
|
121
|
-
console.log(`平均耗时: ${(duration / 5).toFixed(2)}ms`);
|
|
122
|
-
|
|
123
|
-
console.log('\n========== 测试完成 ==========\n');
|
|
124
|
-
} catch (error: any) {
|
|
125
|
-
console.error('\n❌ 测试失败:', error.message);
|
|
126
|
-
console.error(error.stack);
|
|
127
|
-
} finally {
|
|
128
|
-
// 关闭服务器和连接
|
|
129
|
-
server.stop(true);
|
|
130
|
-
await db.close();
|
|
131
|
-
await redis.close();
|
|
132
|
-
process.exit(0);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
testFieldsExclude();
|