befly-tpl 3.10.46 → 3.10.47

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 CHANGED
@@ -37,10 +37,10 @@ bunx befly init
37
37
 
38
38
  ```typescript
39
39
  // main.ts
40
- import { Befly } from 'befly';
40
+ import { Befly } from "befly";
41
41
 
42
42
  const app = new Befly({
43
- appName: 'My API',
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 'befly/types/index';
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: 'Hello, Befly!',
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, BeflyContext } from 'befly/types/index';
85
- import type { User } from './types/models';
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: '用户ID|number|1|999999|null|1|null'
92
+ id: "用户ID|number|1|999999|null|1|null"
92
93
  },
93
- required: ['id'],
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: 'user',
100
+ table: "user",
100
101
  where: { id }
101
102
  });
102
103
 
103
- return { msg: '查询成功', data: user };
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: 'user',
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: 'product',
120
- where: { category: 'electronics' },
120
+ table: "product",
121
+ where: { category: "electronics" },
121
122
  page: 1,
122
123
  limit: 10,
123
- orderBy: ['createdAt#DESC']
124
+ orderBy: ["createdAt#DESC"]
124
125
  });
125
126
 
126
127
  // 插入数据
127
128
  await befly.db.insData({
128
- table: 'user',
129
+ table: "user",
129
130
  data: {
130
- username: 'john',
131
- email: 'john@example.com'
131
+ username: "john",
132
+ email: "john@example.com"
132
133
  }
133
134
  });
134
135
 
135
136
  // 更新数据
136
137
  await befly.db.updData({
137
- table: 'user',
138
+ table: "user",
138
139
  where: { id: 1 },
139
140
  data: {
140
- nickname: 'John Doe'
141
+ nickname: "John Doe"
141
142
  }
142
143
  });
143
144
 
144
145
  // 删除数据
145
146
  await befly.db.delData({
146
- table: 'user',
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
- ```bash
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, ctx) => {
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
@@ -1,4 +1,4 @@
1
- import { Befly } from 'befly';
1
+ import { Befly } from "befly";
2
2
 
3
3
  export const app = new Befly();
4
4
 
package/package.json CHANGED
@@ -1,39 +1,38 @@
1
1
  {
2
2
  "name": "befly-tpl",
3
- "version": "3.10.46",
4
- "description": "Befly 3.0 TypeScript Template",
3
+ "version": "3.10.47",
5
4
  "private": false,
6
- "publishConfig": {
7
- "access": "public",
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
- "README.md",
16
+ "tables",
17
+ "tests",
28
18
  "tsconfig.json"
29
19
  ],
30
- "type": "module",
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.30",
33
- "befly": "^3.9.38"
27
+ "@befly-addon/admin": "^1.1.31",
28
+ "befly": "^3.9.39"
34
29
  },
35
30
  "engines": {
36
31
  "bun": ">=1.3.0"
37
32
  },
38
- "gitHead": "8cb371928961c63d6c3c416c6dd667f8fe285376"
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "registry": "https://registry.npmjs.org"
36
+ },
37
+ "gitHead": "d42bf60ba6b8b11fef7e759fa008ada075829772"
39
38
  }
package/pm2.config.cjs CHANGED
@@ -1,26 +1,26 @@
1
1
  module.exports = {
2
2
  apps: [
3
3
  {
4
- name: 'befly',
5
- script: 'main.ts',
6
- interpreter: 'bun',
4
+ name: "befly",
5
+ script: "main.ts",
6
+ interpreter: "bun",
7
7
 
8
8
  // 集群模式配置
9
9
  instances: 2, // 实例数量,可设置为 'max' 使用所有 CPU
10
- exec_mode: 'cluster', // 集群模式
10
+ exec_mode: "cluster", // 集群模式
11
11
 
12
12
  // 自动重启配置
13
13
  autorestart: true,
14
14
  watch: false,
15
- max_memory_restart: '500M', // 内存超过 500M 自动重启
15
+ max_memory_restart: "500M", // 内存超过 500M 自动重启
16
16
 
17
17
  // 日志配置
18
- log_date_format: 'YYYY-MM-DD HH:mm:ss',
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: 'production'
23
+ NODE_ENV: "production"
24
24
  }
25
25
  }
26
26
  ]
@@ -3,11 +3,11 @@
3
3
  * 验证 fields 的3种写法:空数组、全部包含、全部排除
4
4
  */
5
5
 
6
- import { Befly } from 'befly';
6
+ import { Befly } from "befly";
7
7
 
8
8
  async function testFieldsExclude() {
9
9
  // 强制启用数据库
10
- process.env.DATABASE_ENABLE = '1';
10
+ process.env.DATABASE_ENABLE = "1";
11
11
 
12
12
  // 创建 Befly 实例
13
13
  const befly = new Befly();
@@ -19,100 +19,100 @@ async function testFieldsExclude() {
19
19
  const db = befly.appContext.db;
20
20
  const redis = befly.appContext.redis;
21
21
 
22
- console.log('\n========== 测试开始 ==========\n');
22
+ console.log("\n========== 测试开始 ==========\n");
23
23
 
24
24
  try {
25
25
  // 测试1:空数组(查询所有字段)
26
- console.log('【测试1】空数组 - 查询所有字段');
26
+ console.log("【测试1】空数组 - 查询所有字段");
27
27
  const result1 = await db.getOne({
28
- table: 'addon_admin_user',
28
+ table: "addon_admin_user",
29
29
  fields: [],
30
30
  where: { id: 1 }
31
31
  });
32
- console.log('结果字段数:', Object.keys(result1 || {}).length);
33
- console.log('字段列表:', Object.keys(result1 || {}).join(', '));
32
+ console.log("结果字段数:", Object.keys(result1 || {}).length);
33
+ console.log("字段列表:", Object.keys(result1 || {}).join(", "));
34
34
 
35
35
  // 测试2:指定包含字段
36
- console.log('\n【测试2】指定包含字段 - 只查询 id, name, email');
36
+ console.log("\n【测试2】指定包含字段 - 只查询 id, name, email");
37
37
  const result2 = await db.getOne({
38
- table: 'addon_admin_user',
39
- fields: ['id', 'name', 'email'],
38
+ table: "addon_admin_user",
39
+ fields: ["id", "name", "email"],
40
40
  where: { id: 1 }
41
41
  });
42
- console.log('结果字段数:', Object.keys(result2 || {}).length);
43
- console.log('字段列表:', Object.keys(result2 || {}).join(', '));
42
+ console.log("结果字段数:", Object.keys(result2 || {}).length);
43
+ console.log("字段列表:", Object.keys(result2 || {}).join(", "));
44
44
 
45
45
  // 测试3:排除字段(排除敏感字段)
46
- console.log('\n【测试3】排除字段 - 排除 password, salt');
46
+ console.log("\n【测试3】排除字段 - 排除 password, salt");
47
47
  const result3 = await db.getOne({
48
- table: 'addon_admin_user',
49
- fields: ['!password', '!salt'],
48
+ table: "addon_admin_user",
49
+ fields: ["!password", "!salt"],
50
50
  where: { id: 1 }
51
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 || {}));
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
56
 
57
57
  // 测试4:getList 支持排除字段
58
- console.log('\n【测试4】getList - 排除字段');
58
+ console.log("\n【测试4】getList - 排除字段");
59
59
  const result4 = await db.getList({
60
- table: 'addon_admin_user',
61
- fields: ['!password', '!salt'],
60
+ table: "addon_admin_user",
61
+ fields: ["!password", "!salt"],
62
62
  page: 1,
63
63
  limit: 2
64
64
  });
65
- console.log('查询到记录数:', result4.lists.length);
65
+ console.log("查询到记录数:", result4.lists.length);
66
66
  if (result4.lists.length > 0) {
67
- console.log('第一条记录字段:', Object.keys(result4.lists[0]).join(', '));
68
- console.log('是否包含 password:', 'password' in result4.lists[0]);
67
+ console.log("第一条记录字段:", Object.keys(result4.lists[0]).join(", "));
68
+ console.log("是否包含 password:", "password" in result4.lists[0]);
69
69
  }
70
70
 
71
71
  // 测试5:getAll 支持排除字段
72
- console.log('\n【测试5】getAll - 排除字段');
72
+ console.log("\n【测试5】getAll - 排除字段");
73
73
  const result5 = await db.getAll({
74
- table: 'addon_admin_user',
75
- fields: ['!password', '!salt']
74
+ table: "addon_admin_user",
75
+ fields: ["!password", "!salt"]
76
76
  });
77
- console.log('查询到记录数:', result5.length);
77
+ console.log("查询到记录数:", result5.length);
78
78
  if (result5.length > 0) {
79
- console.log('第一条记录字段:', Object.keys(result5[0]).join(', '));
80
- console.log('是否包含 password:', 'password' in result5[0]);
79
+ console.log("第一条记录字段:", Object.keys(result5[0]).join(", "));
80
+ console.log("是否包含 password:", "password" in result5[0]);
81
81
  }
82
82
 
83
83
  // 测试6:混用检测(应该报错)
84
- console.log('\n【测试6】混用检测 - 应该抛出错误');
84
+ console.log("\n【测试6】混用检测 - 应该抛出错误");
85
85
  try {
86
86
  await db.getOne({
87
- table: 'addon_admin_user',
88
- fields: ['id', '!password'],
87
+ table: "addon_admin_user",
88
+ fields: ["id", "!password"],
89
89
  where: { id: 1 }
90
90
  });
91
- console.log('❌ 没有抛出错误(不符合预期)');
91
+ console.log("❌ 没有抛出错误(不符合预期)");
92
92
  } catch (error: any) {
93
- console.log('✅ 成功捕获错误:', error.message);
93
+ console.log("✅ 成功捕获错误:", error.message);
94
94
  }
95
95
 
96
96
  // 测试7:星号检测(应该报错)
97
- console.log('\n【测试7】星号检测 - 应该抛出错误');
97
+ console.log("\n【测试7】星号检测 - 应该抛出错误");
98
98
  try {
99
99
  await db.getOne({
100
- table: 'addon_admin_user',
101
- fields: ['*'],
100
+ table: "addon_admin_user",
101
+ fields: ["*"],
102
102
  where: { id: 1 }
103
103
  });
104
- console.log('❌ 没有抛出错误(不符合预期)');
104
+ console.log("❌ 没有抛出错误(不符合预期)");
105
105
  } catch (error: any) {
106
- console.log('✅ 成功捕获错误:', error.message);
106
+ console.log("✅ 成功捕获错误:", error.message);
107
107
  }
108
108
 
109
109
  // 测试8:缓存性能测试
110
- console.log('\n【测试8】缓存性能测试 - 多次查询相同表');
110
+ console.log("\n【测试8】缓存性能测试 - 多次查询相同表");
111
111
  const start = Date.now();
112
112
  for (let i = 0; i < 5; i++) {
113
113
  await db.getOne({
114
- table: 'addon_admin_user',
115
- fields: ['!password', '!salt'],
114
+ table: "addon_admin_user",
115
+ fields: ["!password", "!salt"],
116
116
  where: { id: 1 }
117
117
  });
118
118
  }
@@ -120,9 +120,9 @@ async function testFieldsExclude() {
120
120
  console.log(`5次查询总耗时: ${duration}ms`);
121
121
  console.log(`平均耗时: ${(duration / 5).toFixed(2)}ms`);
122
122
 
123
- console.log('\n========== 测试完成 ==========\n');
123
+ console.log("\n========== 测试完成 ==========\n");
124
124
  } catch (error: any) {
125
- console.error('\n❌ 测试失败:', error.message);
125
+ console.error("\n❌ 测试失败:", error.message);
126
126
  console.error(error.stack);
127
127
  } finally {
128
128
  // 关闭服务器和连接
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-types"],
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
- };