befly-shared 1.2.7 → 1.3.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.
- package/package.json +13 -30
- package/utils/arrayToTree.ts +135 -0
- package/utils/buildTreeByParentPath.ts +127 -0
- package/utils/scanViewsDir.ts +148 -0
- package/README.md +0 -439
- package/dist/addonHelper.js +0 -83
- package/dist/arrayKeysToCamel.js +0 -18
- package/dist/arrayToTree.js +0 -23
- package/dist/calcPerfTime.js +0 -13
- package/dist/configTypes.js +0 -1
- package/dist/constants.js +0 -46
- package/dist/fieldClear.js +0 -57
- package/dist/genShortId.js +0 -12
- package/dist/hashPassword.js +0 -22
- package/dist/index.js +0 -25
- package/dist/keysToCamel.js +0 -21
- package/dist/keysToSnake.js +0 -21
- package/dist/layouts.js +0 -59
- package/dist/pickFields.js +0 -16
- package/dist/redisKeys.js +0 -34
- package/dist/regex.js +0 -202
- package/dist/scanConfig.js +0 -83
- package/dist/scanFiles.js +0 -39
- package/dist/scanViews.js +0 -48
- package/dist/withDefaultColumns.js +0 -32
- package/src/addonHelper.ts +0 -88
- package/src/arrayKeysToCamel.ts +0 -18
- package/src/arrayToTree.ts +0 -31
- package/src/calcPerfTime.ts +0 -13
- package/src/configTypes.ts +0 -29
- package/src/constants.ts +0 -60
- package/src/fieldClear.ts +0 -75
- package/src/genShortId.ts +0 -12
- package/src/hashPassword.ts +0 -27
- package/src/index.ts +0 -28
- package/src/keysToCamel.ts +0 -22
- package/src/keysToSnake.ts +0 -22
- package/src/layouts.ts +0 -90
- package/src/pickFields.ts +0 -19
- package/src/redisKeys.ts +0 -44
- package/src/regex.ts +0 -225
- package/src/scanConfig.ts +0 -106
- package/src/scanFiles.ts +0 -49
- package/src/scanViews.ts +0 -55
- package/src/withDefaultColumns.ts +0 -36
- package/tests/addonHelper.test.ts +0 -55
- package/tests/arrayKeysToCamel.test.ts +0 -21
- package/tests/arrayToTree.test.ts +0 -98
- package/tests/calcPerfTime.test.ts +0 -19
- package/tests/fieldClear.test.ts +0 -39
- package/tests/keysToCamel.test.ts +0 -22
- package/tests/keysToSnake.test.ts +0 -22
- package/tests/layouts.test.ts +0 -93
- package/tests/pickFields.test.ts +0 -22
- package/tests/regex.test.ts +0 -308
- package/tests/scanFiles.test.ts +0 -58
- package/tests/types.test.ts +0 -289
- package/types/addon.d.ts +0 -50
- package/types/addonConfigMerge.d.ts +0 -17
- package/types/addonHelper.d.ts +0 -24
- package/types/api.d.ts +0 -63
- package/types/arrayKeysToCamel.d.ts +0 -13
- package/types/arrayToTree.d.ts +0 -8
- package/types/calcPerfTime.d.ts +0 -4
- package/types/common.d.ts +0 -8
- package/types/configMerge.d.ts +0 -49
- package/types/configTypes.d.ts +0 -28
- package/types/constants.d.ts +0 -48
- package/types/context.d.ts +0 -38
- package/types/crypto.d.ts +0 -23
- package/types/database.d.ts +0 -55
- package/types/fieldClear.d.ts +0 -16
- package/types/genShortId.d.ts +0 -10
- package/types/hashPassword.d.ts +0 -11
- package/types/index.d.ts +0 -22
- package/types/jwt.d.ts +0 -99
- package/types/keysToCamel.d.ts +0 -10
- package/types/keysToSnake.d.ts +0 -10
- package/types/layouts.d.ts +0 -29
- package/types/loadAndMergeConfig.d.ts +0 -7
- package/types/logger.d.ts +0 -22
- package/types/menu.d.ts +0 -49
- package/types/mergeConfig.d.ts +0 -7
- package/types/pickFields.d.ts +0 -4
- package/types/redisKeys.d.ts +0 -34
- package/types/regex.d.ts +0 -145
- package/types/scanConfig.d.ts +0 -7
- package/types/scanFiles.d.ts +0 -12
- package/types/scanViews.d.ts +0 -11
- package/types/table.d.ts +0 -49
- package/types/tool.d.ts +0 -67
- package/types/types.d.ts +0 -44
- package/types/validate.d.ts +0 -69
- package/types/withDefaultColumns.d.ts +0 -7
package/README.md
DELETED
|
@@ -1,439 +0,0 @@
|
|
|
1
|
-
# Befly Shared
|
|
2
|
-
|
|
3
|
-
Befly 框架的共享模块,包含跨包共享的工具函数、常量、类型定义和配置。
|
|
4
|
-
|
|
5
|
-
## 安装
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun add befly-shared
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## 类型定义
|
|
12
|
-
|
|
13
|
-
所有类型统一从 `befly-shared/types` 导入,按功能分类:
|
|
14
|
-
|
|
15
|
-
| 分类 | 类型 |
|
|
16
|
-
| ------ | ----------------------------------------------------------------------------- |
|
|
17
|
-
| 验证 | `ValidateResult`, `SingleResult`, `FieldDefinition`, `FieldRules` |
|
|
18
|
-
| API | `ResponseResult`, `PaginatedResult`, `ApiCode`, `ErrorMessages` |
|
|
19
|
-
| 数据库 | `DatabaseConfig`, `SqlValue`, `WhereConditions` |
|
|
20
|
-
| 上下文 | `RequestContext`, `ApiRoute` |
|
|
21
|
-
| 菜单 | `MenuItem`, `MenuTree` |
|
|
22
|
-
| 加密 | `EncodingType`, `HashAlgorithm`, `PasswordHashOptions` |
|
|
23
|
-
| JWT | `JwtPayload`, `JwtSignOptions`, `JwtVerifyOptions`, `JwtDecoded`, `JwtHeader` |
|
|
24
|
-
| 日志 | `LogLevel`, `LoggerConfig` |
|
|
25
|
-
| 工具 | `DateFormat`, `PaginationParams`, `PaginationResult` |
|
|
26
|
-
| 表 | `SystemFields`, `BaseTable`, `InsertType`, `UpdateType`, `SelectType` |
|
|
27
|
-
| Addon | `AddonAuthor`, `AddonConfig` |
|
|
28
|
-
| 通用 | `ReservedFields`, `ExcludeReserved` |
|
|
29
|
-
|
|
30
|
-
### 响应类型
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
import type { ResponseResult, PaginatedResult, ValidationResult } from 'befly-shared/types';
|
|
34
|
-
|
|
35
|
-
// API 响应
|
|
36
|
-
const result: ResponseResult<{ id: number }> = {
|
|
37
|
-
code: 0,
|
|
38
|
-
msg: '操作成功',
|
|
39
|
-
data: { id: 1 }
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// 分页响应
|
|
43
|
-
const list: PaginatedResult<User> = {
|
|
44
|
-
code: 0,
|
|
45
|
-
msg: '查询成功',
|
|
46
|
-
data: users,
|
|
47
|
-
total: 100,
|
|
48
|
-
page: 1,
|
|
49
|
-
limit: 10,
|
|
50
|
-
pages: 10
|
|
51
|
-
};
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 常量
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
import { ApiCode, ErrorMessages } from 'befly-shared/types';
|
|
58
|
-
|
|
59
|
-
// 响应码
|
|
60
|
-
ApiCode.SUCCESS; // 0
|
|
61
|
-
ApiCode.FAIL; // 1
|
|
62
|
-
ApiCode.UNAUTHORIZED; // 401
|
|
63
|
-
ApiCode.FORBIDDEN; // 403
|
|
64
|
-
ApiCode.NOT_FOUND; // 404
|
|
65
|
-
ApiCode.SERVER_ERROR; // 500
|
|
66
|
-
|
|
67
|
-
// 错误消息
|
|
68
|
-
ErrorMessages.UNAUTHORIZED; // '请先登录'
|
|
69
|
-
ErrorMessages.FORBIDDEN; // '无访问权限'
|
|
70
|
-
ErrorMessages.TOKEN_EXPIRED; // 'Token 已过期'
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### 配置类型
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import type { DatabaseConfig, RedisConfig } from 'befly-shared/types';
|
|
77
|
-
|
|
78
|
-
const dbConfig: DatabaseConfig = {
|
|
79
|
-
type: 'mysql',
|
|
80
|
-
host: 'localhost',
|
|
81
|
-
port: 3306,
|
|
82
|
-
username: 'root',
|
|
83
|
-
password: 'password',
|
|
84
|
-
database: 'befly'
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const redisConfig: RedisConfig = {
|
|
88
|
-
host: 'localhost',
|
|
89
|
-
port: 6379,
|
|
90
|
-
password: 'password',
|
|
91
|
-
db: 0,
|
|
92
|
-
prefix: 'befly:'
|
|
93
|
-
};
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
> **注意**:这些类型主要用于类型检查和文档,实际连接时框架会自动从 `beflyConfig` 获取配置。
|
|
97
|
-
|
|
98
|
-
### Redis 键和 TTL
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { RedisKeys, RedisTTL } from 'befly-shared/redisKeys';
|
|
102
|
-
|
|
103
|
-
// 生成 Redis 键
|
|
104
|
-
RedisKeys.apisAll(); // 'befly:apis:all'
|
|
105
|
-
RedisKeys.menusAll(); // 'befly:menus:all'
|
|
106
|
-
RedisKeys.roleInfo('admin'); // 'befly:role:info:admin'
|
|
107
|
-
RedisKeys.roleApis('admin'); // 'befly:role:apis:admin'
|
|
108
|
-
RedisKeys.tableColumns('user'); // 'befly:table:columns:user'
|
|
109
|
-
|
|
110
|
-
// TTL 配置(秒)
|
|
111
|
-
RedisTTL.tableColumns; // 3600 (1小时)
|
|
112
|
-
RedisTTL.roleApis; // 86400 (24小时)
|
|
113
|
-
RedisTTL.roleInfo; // 86400 (24小时)
|
|
114
|
-
RedisTTL.apisAll; // null (永久)
|
|
115
|
-
RedisTTL.menusAll; // null (永久)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## 配置管理
|
|
119
|
-
|
|
120
|
-
### mergeConfig
|
|
121
|
-
|
|
122
|
-
加载并合并配置文件(矩阵搜索:dirs × files)。
|
|
123
|
-
|
|
124
|
-
**参数:**
|
|
125
|
-
|
|
126
|
-
- `dirs`: 目录数组(绝对路径)
|
|
127
|
-
- `files`: 文件名数组(不含扩展名)
|
|
128
|
-
- `required`: 是否必填,默认 `false`
|
|
129
|
-
- `extensions`: 扩展名数组,默认 `['.js', '.ts', '.json']`
|
|
130
|
-
|
|
131
|
-
**返回:** `Promise<Record<string, any>>`
|
|
132
|
-
|
|
133
|
-
**示例:**
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
import { mergeConfig } from 'befly-shared/scanConfig';
|
|
137
|
-
|
|
138
|
-
const config = await mergeConfig({
|
|
139
|
-
dirs: ['/path/to/config1', '/path/to/config2'],
|
|
140
|
-
files: ['app', 'database'],
|
|
141
|
-
required: false
|
|
142
|
-
});
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## 字段名转换
|
|
146
|
-
|
|
147
|
-
### keysToCamel
|
|
148
|
-
|
|
149
|
-
将对象字段名转为小驼峰格式。
|
|
150
|
-
|
|
151
|
-
**参数:**
|
|
152
|
-
|
|
153
|
-
- `obj`: 源对象
|
|
154
|
-
|
|
155
|
-
**返回:** `T`
|
|
156
|
-
|
|
157
|
-
**示例:**
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
import { keysToCamel } from 'befly-shared/keysToCamel';
|
|
161
|
-
|
|
162
|
-
keysToCamel({ user_id: 123, user_name: 'John' });
|
|
163
|
-
// { userId: 123, userName: 'John' }
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### keysToSnake
|
|
167
|
-
|
|
168
|
-
将对象字段名转为下划线格式。
|
|
169
|
-
|
|
170
|
-
**参数:**
|
|
171
|
-
|
|
172
|
-
- `obj`: 源对象
|
|
173
|
-
|
|
174
|
-
**返回:** `T`
|
|
175
|
-
|
|
176
|
-
**示例:**
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
import { keysToSnake } from 'befly-shared/keysToSnake';
|
|
180
|
-
|
|
181
|
-
keysToSnake({ userId: 123, userName: 'John' });
|
|
182
|
-
// { user_id: 123, user_name: 'John' }
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### arrayKeysToCamel
|
|
186
|
-
|
|
187
|
-
批量将数组对象的字段名转为小驼峰格式。
|
|
188
|
-
|
|
189
|
-
**参数:**
|
|
190
|
-
|
|
191
|
-
- `arr`: 源数组
|
|
192
|
-
|
|
193
|
-
**返回:** `T[]`
|
|
194
|
-
|
|
195
|
-
**示例:**
|
|
196
|
-
|
|
197
|
-
```typescript
|
|
198
|
-
import { arrayKeysToCamel } from 'befly-shared/arrayKeysToCamel';
|
|
199
|
-
|
|
200
|
-
arrayKeysToCamel([
|
|
201
|
-
{ user_id: 1, user_name: 'John' },
|
|
202
|
-
{ user_id: 2, user_name: 'Jane' }
|
|
203
|
-
]);
|
|
204
|
-
// [{ userId: 1, userName: 'John' }, { userId: 2, userName: 'Jane' }]
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## 数据处理
|
|
208
|
-
|
|
209
|
-
### arrayToTree
|
|
210
|
-
|
|
211
|
-
将扁平数组转为树形结构。
|
|
212
|
-
|
|
213
|
-
**参数:**
|
|
214
|
-
|
|
215
|
-
- `items`: 数组
|
|
216
|
-
- `options`: 配置项
|
|
217
|
-
- `idField`: 节点 id 字段名,默认 `'id'`
|
|
218
|
-
- `pidField`: 父节点 id 字段名,默认 `'pid'`
|
|
219
|
-
- `childrenField`: 子节点字段名,默认 `'children'`
|
|
220
|
-
- `rootPid`: 根节点的父 id,默认 `0`
|
|
221
|
-
- `mapFn`: 节点转换函数(可选)
|
|
222
|
-
|
|
223
|
-
**返回:** `T[]`
|
|
224
|
-
|
|
225
|
-
**示例:**
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
import { arrayToTree } from 'befly-shared/arrayToTree';
|
|
229
|
-
|
|
230
|
-
const items = [
|
|
231
|
-
{ id: 1, pid: 0, name: '根节点' },
|
|
232
|
-
{ id: 2, pid: 1, name: '子节点1' },
|
|
233
|
-
{ id: 3, pid: 1, name: '子节点2' }
|
|
234
|
-
];
|
|
235
|
-
|
|
236
|
-
const tree = arrayToTree(items);
|
|
237
|
-
// [
|
|
238
|
-
// {
|
|
239
|
-
// id: 1, pid: 0, name: '根节点',
|
|
240
|
-
// children: [
|
|
241
|
-
// { id: 2, pid: 1, name: '子节点1' },
|
|
242
|
-
// { id: 3, pid: 1, name: '子节点2' }
|
|
243
|
-
// ]
|
|
244
|
-
// }
|
|
245
|
-
// ]
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### fieldClear
|
|
249
|
-
|
|
250
|
-
字段过滤和清理工具,支持字段挑选、排除、值保留、值排除等操作。
|
|
251
|
-
|
|
252
|
-
**参数:**
|
|
253
|
-
|
|
254
|
-
- `data`: 数据(对象或数组)
|
|
255
|
-
- `options`: 配置项
|
|
256
|
-
- `pickKeys`: 只保留这些字段
|
|
257
|
-
- `omitKeys`: 排除这些字段
|
|
258
|
-
- `keepValues`: 只保留这些值
|
|
259
|
-
- `excludeValues`: 排除这些值
|
|
260
|
-
- `keepMap`: 强制保留的键值对(优先级最高)
|
|
261
|
-
|
|
262
|
-
**返回:** `FieldClearResult<T>`
|
|
263
|
-
|
|
264
|
-
**示例:**
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
import { fieldClear } from 'befly-shared/fieldClear';
|
|
268
|
-
|
|
269
|
-
// 只保留指定字段
|
|
270
|
-
fieldClear({ id: 1, name: 'John', age: 30 }, { pickKeys: ['id', 'name'] });
|
|
271
|
-
// { id: 1, name: 'John' }
|
|
272
|
-
|
|
273
|
-
// 排除指定字段
|
|
274
|
-
fieldClear({ id: 1, name: 'John', age: 30 }, { omitKeys: ['age'] });
|
|
275
|
-
// { id: 1, name: 'John' }
|
|
276
|
-
|
|
277
|
-
// 排除指定值
|
|
278
|
-
fieldClear({ id: 1, name: null, age: undefined }, { excludeValues: [null, undefined] });
|
|
279
|
-
// { id: 1 }
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### pickFields
|
|
283
|
-
|
|
284
|
-
挑选对象中的指定字段。
|
|
285
|
-
|
|
286
|
-
**参数:**
|
|
287
|
-
|
|
288
|
-
- `obj`: 源对象
|
|
289
|
-
- `keys`: 字段名数组
|
|
290
|
-
|
|
291
|
-
**返回:** `Partial<T>`
|
|
292
|
-
|
|
293
|
-
**示例:**
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
import { pickFields } from 'befly-shared/pickFields';
|
|
297
|
-
|
|
298
|
-
pickFields({ id: 1, name: 'John', age: 30 }, ['id', 'name']);
|
|
299
|
-
// { id: 1, name: 'John' }
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## 文件扫描
|
|
303
|
-
|
|
304
|
-
### scanFiles
|
|
305
|
-
|
|
306
|
-
扫描指定目录下的文件。
|
|
307
|
-
|
|
308
|
-
**参数:**
|
|
309
|
-
|
|
310
|
-
- `dir`: 目录路径
|
|
311
|
-
- `pattern`: Glob 模式,默认 `'**/*.{ts,js}'`
|
|
312
|
-
- `ignoreUnderline`: 是否忽略下划线开头的文件/目录,默认 `true`
|
|
313
|
-
|
|
314
|
-
**返回:** `Promise<ScanFileResult[]>`
|
|
315
|
-
|
|
316
|
-
**示例:**
|
|
317
|
-
|
|
318
|
-
```typescript
|
|
319
|
-
import { scanFiles } from 'befly-shared/scanFiles';
|
|
320
|
-
|
|
321
|
-
const files = await scanFiles('/path/to/dir', '**/*.ts');
|
|
322
|
-
// [
|
|
323
|
-
// { filePath: '/path/to/dir/file1.ts', relativePath: 'file1', fileName: 'file1' },
|
|
324
|
-
// { filePath: '/path/to/dir/sub/file2.ts', relativePath: 'sub/file2', fileName: 'file2' }
|
|
325
|
-
// ]
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### scanViews
|
|
329
|
-
|
|
330
|
-
扫描项目和所有 `@befly-addon` 包的 views 目录,用于 unplugin-vue-router 的 routesFolder 配置。
|
|
331
|
-
|
|
332
|
-
**注意:** 此函数只能在 vite.config.js 中使用(Node.js 环境),不能在浏览器中使用。
|
|
333
|
-
|
|
334
|
-
**返回:** 路由文件夹配置数组
|
|
335
|
-
|
|
336
|
-
**示例:**
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
import { scanViews } from 'befly-shared/scanViews';
|
|
340
|
-
|
|
341
|
-
// 在 vite.config.js 中使用
|
|
342
|
-
export default defineConfig({
|
|
343
|
-
plugins: [
|
|
344
|
-
VueRouter({
|
|
345
|
-
routesFolder: scanViews()
|
|
346
|
-
})
|
|
347
|
-
]
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### scanAddons
|
|
352
|
-
|
|
353
|
-
扫描所有可用的 addon,从 `node_modules/@befly-addon/` 加载。
|
|
354
|
-
|
|
355
|
-
**参数:**
|
|
356
|
-
|
|
357
|
-
- `cwd`: 项目根目录,默认 `process.cwd()`
|
|
358
|
-
|
|
359
|
-
**返回:** `string[]` - addon 名称数组
|
|
360
|
-
|
|
361
|
-
**示例:**
|
|
362
|
-
|
|
363
|
-
```typescript
|
|
364
|
-
import { scanAddons } from 'befly-shared/addonHelper';
|
|
365
|
-
|
|
366
|
-
const addons = scanAddons();
|
|
367
|
-
// ['admin', 'blog', 'shop']
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
## 路由处理
|
|
371
|
-
|
|
372
|
-
### layouts
|
|
373
|
-
|
|
374
|
-
自定义布局处理函数,根据文件名后缀判断使用哪个布局。
|
|
375
|
-
|
|
376
|
-
**参数:**
|
|
377
|
-
|
|
378
|
-
- `routes`: 原始路由配置
|
|
379
|
-
- `inheritLayout`: 继承的布局名称(来自父级目录)
|
|
380
|
-
|
|
381
|
-
**返回:** 处理后的布局配置
|
|
382
|
-
|
|
383
|
-
**示例:**
|
|
384
|
-
|
|
385
|
-
```typescript
|
|
386
|
-
import { layouts } from 'befly-shared/layouts';
|
|
387
|
-
|
|
388
|
-
// 根据文件名后缀判断布局:
|
|
389
|
-
// - index.vue -> 默认布局
|
|
390
|
-
// - login_n.vue -> n 布局
|
|
391
|
-
// - admin_a.vue -> a 布局
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
## 性能工具
|
|
395
|
-
|
|
396
|
-
### calcPerfTime
|
|
397
|
-
|
|
398
|
-
计算性能时间差(支持纳秒级精度)。
|
|
399
|
-
|
|
400
|
-
**参数:**
|
|
401
|
-
|
|
402
|
-
- `startTime`: 开始时间(纳秒)
|
|
403
|
-
- `endTime`: 结束时间(纳秒),默认 `Bun.nanoseconds()`
|
|
404
|
-
|
|
405
|
-
**返回:** `string` - 格式化的时间字符串
|
|
406
|
-
|
|
407
|
-
**示例:**
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
import { calcPerfTime } from 'befly-shared/calcPerfTime';
|
|
411
|
-
|
|
412
|
-
const start = Bun.nanoseconds();
|
|
413
|
-
// ... 执行操作 ...
|
|
414
|
-
const duration = calcPerfTime(start);
|
|
415
|
-
// "12.34 毫秒" 或 "1.23 秒"
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
## Addon 辅助
|
|
419
|
-
|
|
420
|
-
### addonHelper
|
|
421
|
-
|
|
422
|
-
提供 addon 相关的辅助功能,包括扫描、路径解析等。
|
|
423
|
-
|
|
424
|
-
**导出函数:**
|
|
425
|
-
|
|
426
|
-
- `scanAddons(cwd?)`: 扫描所有可用的 addon
|
|
427
|
-
- 其他辅助函数...
|
|
428
|
-
|
|
429
|
-
## 类型定义
|
|
430
|
-
|
|
431
|
-
所有类型定义自动生成到 `types/` 目录下,可直接导入使用:
|
|
432
|
-
|
|
433
|
-
```typescript
|
|
434
|
-
import type { LoadConfigOptions, MergeConfigOptions } from 'befly-shared/configTypes';
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
## License
|
|
438
|
-
|
|
439
|
-
Apache-2.0
|
package/dist/addonHelper.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { join } from 'pathe';
|
|
3
|
-
import { statSync, existsSync } from 'node:fs';
|
|
4
|
-
/**
|
|
5
|
-
* 扫描所有可用的 addon
|
|
6
|
-
* 优先从本地 addons/ 目录加载,其次从 node_modules/@befly-addon/ 加载
|
|
7
|
-
* @param cwd - 项目根目录,默认为 process.cwd()
|
|
8
|
-
* @returns addon 名称数组
|
|
9
|
-
*/
|
|
10
|
-
export const scanAddons = (cwd = process.cwd()) => {
|
|
11
|
-
const addons = new Set();
|
|
12
|
-
// const projectAddonsDir = join(cwd, 'addons');
|
|
13
|
-
// 1. 扫描本地 addons 目录(优先级高)
|
|
14
|
-
// if (existsSync(projectAddonsDir)) {
|
|
15
|
-
// try {
|
|
16
|
-
// const localAddons = fs.readdirSync(projectAddonsDir).filter((name) => {
|
|
17
|
-
// const fullPath = join(projectAddonsDir, name);
|
|
18
|
-
// try {
|
|
19
|
-
// const stat = statSync(fullPath);
|
|
20
|
-
// return stat.isDirectory() && !name.startsWith('_');
|
|
21
|
-
// } catch {
|
|
22
|
-
// return false;
|
|
23
|
-
// }
|
|
24
|
-
// });
|
|
25
|
-
// localAddons.forEach((name) => addons.add(name));
|
|
26
|
-
// } catch (err) {
|
|
27
|
-
// // 忽略本地目录读取错误
|
|
28
|
-
// }
|
|
29
|
-
// }
|
|
30
|
-
// 2. 扫描 node_modules/@befly-addon 目录
|
|
31
|
-
const beflyDir = join(cwd, 'node_modules', '@befly-addon');
|
|
32
|
-
if (existsSync(beflyDir)) {
|
|
33
|
-
try {
|
|
34
|
-
const npmAddons = fs.readdirSync(beflyDir).filter((name) => {
|
|
35
|
-
// 如果本地已存在,跳过 npm 包版本
|
|
36
|
-
if (addons.has(name))
|
|
37
|
-
return false;
|
|
38
|
-
const fullPath = join(beflyDir, name);
|
|
39
|
-
try {
|
|
40
|
-
const stat = statSync(fullPath);
|
|
41
|
-
return stat.isDirectory();
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
npmAddons.forEach((name) => addons.add(name));
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// 忽略 npm 目录读取错误
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return Array.from(addons).sort();
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* 获取 addon 的指定子目录路径
|
|
57
|
-
* 优先返回本地 addons 目录,其次返回 node_modules 目录
|
|
58
|
-
* @param name - addon 名称
|
|
59
|
-
* @param subDir - 子目录名称
|
|
60
|
-
* @param cwd - 项目根目录,默认为 process.cwd()
|
|
61
|
-
* @returns 完整路径
|
|
62
|
-
*/
|
|
63
|
-
export const getAddonDir = (name, subDir, cwd = process.cwd()) => {
|
|
64
|
-
// 优先使用本地 addons 目录
|
|
65
|
-
// const projectAddonsDir = join(cwd, 'addons');
|
|
66
|
-
// const localPath = join(projectAddonsDir, name, subDir);
|
|
67
|
-
// if (existsSync(localPath)) {
|
|
68
|
-
// return localPath;
|
|
69
|
-
// }
|
|
70
|
-
// 降级使用 node_modules 目录
|
|
71
|
-
return join(cwd, 'node_modules', '@befly-addon', name, subDir);
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* 检查 addon 子目录是否存在
|
|
75
|
-
* @param name - addon 名称
|
|
76
|
-
* @param subDir - 子目录名称
|
|
77
|
-
* @param cwd - 项目根目录,默认为 process.cwd()
|
|
78
|
-
* @returns 是否存在
|
|
79
|
-
*/
|
|
80
|
-
export const addonDirExists = (name, subDir, cwd = process.cwd()) => {
|
|
81
|
-
const dir = getAddonDir(name, subDir, cwd);
|
|
82
|
-
return existsSync(dir) && statSync(dir).isDirectory();
|
|
83
|
-
};
|
package/dist/arrayKeysToCamel.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { keysToCamel } from './keysToCamel.js';
|
|
2
|
-
/**
|
|
3
|
-
* 数组对象字段名批量转小驼峰
|
|
4
|
-
* @param arr - 源数组
|
|
5
|
-
* @returns 字段名转为小驼峰格式的新数组
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* arrayKeysToCamel([
|
|
9
|
-
* { user_id: 1, user_name: 'John' },
|
|
10
|
-
* { user_id: 2, user_name: 'Jane' }
|
|
11
|
-
* ])
|
|
12
|
-
* // [{ userId: 1, userName: 'John' }, { userId: 2, userName: 'Jane' }]
|
|
13
|
-
*/
|
|
14
|
-
export const arrayKeysToCamel = (arr) => {
|
|
15
|
-
if (!arr || !Array.isArray(arr))
|
|
16
|
-
return arr;
|
|
17
|
-
return arr.map((item) => keysToCamel(item));
|
|
18
|
-
};
|
package/dist/arrayToTree.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// arrayToTree 工具函数实现
|
|
2
|
-
export function arrayToTree(items, options = {}) {
|
|
3
|
-
const { idField = 'id', pidField = 'pid', childrenField = 'children', rootPid = 0, mapFn } = options;
|
|
4
|
-
const tree = [];
|
|
5
|
-
for (const item of items) {
|
|
6
|
-
const pid = item[pidField];
|
|
7
|
-
// 用 Object.is 判断,兼容 null/undefined/0
|
|
8
|
-
if (Object.is(pid, rootPid)) {
|
|
9
|
-
let node = { ...item };
|
|
10
|
-
if (mapFn)
|
|
11
|
-
node = mapFn(node);
|
|
12
|
-
const children = arrayToTree(items, {
|
|
13
|
-
...options,
|
|
14
|
-
rootPid: node[idField]
|
|
15
|
-
});
|
|
16
|
-
if (children.length > 0) {
|
|
17
|
-
node[childrenField] = children;
|
|
18
|
-
}
|
|
19
|
-
tree.push(node);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return tree;
|
|
23
|
-
}
|
package/dist/calcPerfTime.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 计算性能时间差
|
|
3
|
-
*/
|
|
4
|
-
export const calcPerfTime = (startTime, endTime = Bun.nanoseconds()) => {
|
|
5
|
-
const elapsedMs = (endTime - startTime) / 1_000_000;
|
|
6
|
-
if (elapsedMs < 1000) {
|
|
7
|
-
return `${elapsedMs.toFixed(2)} 毫秒`;
|
|
8
|
-
}
|
|
9
|
-
else {
|
|
10
|
-
const elapsedSeconds = elapsedMs / 1000;
|
|
11
|
-
return `${elapsedSeconds.toFixed(2)} 秒`;
|
|
12
|
-
}
|
|
13
|
-
};
|
package/dist/configTypes.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/constants.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Befly 共享常量定义
|
|
3
|
-
* 运行时使用的常量(非纯类型)
|
|
4
|
-
*/
|
|
5
|
-
// ============================================
|
|
6
|
-
// API 响应码常量
|
|
7
|
-
// ============================================
|
|
8
|
-
/**
|
|
9
|
-
* API 响应码
|
|
10
|
-
*/
|
|
11
|
-
export const ApiCode = {
|
|
12
|
-
/** 成功 */
|
|
13
|
-
SUCCESS: 0,
|
|
14
|
-
/** 通用失败 */
|
|
15
|
-
FAIL: 1,
|
|
16
|
-
/** 未授权 */
|
|
17
|
-
UNAUTHORIZED: 401,
|
|
18
|
-
/** 禁止访问 */
|
|
19
|
-
FORBIDDEN: 403,
|
|
20
|
-
/** 未找到 */
|
|
21
|
-
NOT_FOUND: 404,
|
|
22
|
-
/** 服务器错误 */
|
|
23
|
-
SERVER_ERROR: 500
|
|
24
|
-
};
|
|
25
|
-
// ============================================
|
|
26
|
-
// 错误消息常量
|
|
27
|
-
// ============================================
|
|
28
|
-
/**
|
|
29
|
-
* 通用错误消息
|
|
30
|
-
*/
|
|
31
|
-
export const ErrorMessages = {
|
|
32
|
-
/** 未授权 */
|
|
33
|
-
UNAUTHORIZED: '请先登录',
|
|
34
|
-
/** 禁止访问 */
|
|
35
|
-
FORBIDDEN: '无访问权限',
|
|
36
|
-
/** 未找到 */
|
|
37
|
-
NOT_FOUND: '资源不存在',
|
|
38
|
-
/** 服务器错误 */
|
|
39
|
-
SERVER_ERROR: '服务器错误',
|
|
40
|
-
/** 参数错误 */
|
|
41
|
-
INVALID_PARAMS: '参数错误',
|
|
42
|
-
/** Token 过期 */
|
|
43
|
-
TOKEN_EXPIRED: 'Token 已过期',
|
|
44
|
-
/** Token 无效 */
|
|
45
|
-
TOKEN_INVALID: 'Token 无效'
|
|
46
|
-
};
|
package/dist/fieldClear.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// fieldClear 工具函数实现
|
|
2
|
-
// 支持 pick/omit/keepValues/excludeValues,处理对象和数组
|
|
3
|
-
function isObject(val) {
|
|
4
|
-
return val !== null && typeof val === 'object' && !Array.isArray(val);
|
|
5
|
-
}
|
|
6
|
-
function isArray(val) {
|
|
7
|
-
return Array.isArray(val);
|
|
8
|
-
}
|
|
9
|
-
export function fieldClear(data, options = {}) {
|
|
10
|
-
const { pickKeys, omitKeys, keepValues, excludeValues, keepMap } = options;
|
|
11
|
-
const filterObj = (obj) => {
|
|
12
|
-
let result = {};
|
|
13
|
-
let keys = Object.keys(obj);
|
|
14
|
-
if (pickKeys && pickKeys.length) {
|
|
15
|
-
keys = keys.filter((k) => pickKeys.includes(k));
|
|
16
|
-
}
|
|
17
|
-
if (omitKeys && omitKeys.length) {
|
|
18
|
-
keys = keys.filter((k) => !omitKeys.includes(k));
|
|
19
|
-
}
|
|
20
|
-
for (const key of keys) {
|
|
21
|
-
const value = obj[key];
|
|
22
|
-
// 1. 优先检查 keepMap
|
|
23
|
-
if (keepMap && key in keepMap) {
|
|
24
|
-
if (Object.is(keepMap[key], value)) {
|
|
25
|
-
result[key] = value;
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// 2. 检查 keepValues (只保留指定值)
|
|
30
|
-
if (keepValues && keepValues.length && !keepValues.includes(value)) {
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
// 3. 检查 excludeValues (排除指定值)
|
|
34
|
-
if (excludeValues && excludeValues.length && excludeValues.includes(value)) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
result[key] = value;
|
|
38
|
-
}
|
|
39
|
-
return result;
|
|
40
|
-
};
|
|
41
|
-
if (isArray(data)) {
|
|
42
|
-
return data
|
|
43
|
-
.map((item) => (isObject(item) ? filterObj(item) : item))
|
|
44
|
-
.filter((item) => {
|
|
45
|
-
if (isObject(item)) {
|
|
46
|
-
// 只保留有内容的对象
|
|
47
|
-
return Object.keys(item).length > 0;
|
|
48
|
-
}
|
|
49
|
-
// 原始值直接保留
|
|
50
|
-
return true;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
if (isObject(data)) {
|
|
54
|
-
return filterObj(data);
|
|
55
|
-
}
|
|
56
|
-
return data;
|
|
57
|
-
}
|
package/dist/genShortId.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 生成短 ID
|
|
3
|
-
* 由时间戳(base36)+ 随机字符组成,约 13 位
|
|
4
|
-
* - 前 8 位:时间戳(可排序)
|
|
5
|
-
* - 后 5 位:随机字符(防冲突)
|
|
6
|
-
* @returns 短 ID 字符串
|
|
7
|
-
* @example
|
|
8
|
-
* genShortId() // "lxyz1a2b3c4"
|
|
9
|
-
*/
|
|
10
|
-
export function genShortId() {
|
|
11
|
-
return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
|
|
12
|
-
}
|