befly 3.76.1 → 3.76.3
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/Befly.js +159 -0
- package/README.md +50 -11
- package/apis/admin/delete.js +1 -3
- package/apis/admin/select.js +2 -7
- package/apis/admin/update.js +1 -5
- package/apis/api/select.js +2 -7
- package/apis/auth/login.js +16 -20
- package/apis/dict/delete.js +1 -1
- package/apis/dict/detail.js +1 -3
- package/apis/dict/select.js +1 -2
- package/apis/dict/update.js +1 -1
- package/apis/dictType/delete.js +1 -1
- package/apis/dictType/detail.js +1 -1
- package/apis/dictType/insert.js +1 -1
- package/apis/dictType/select.js +2 -7
- package/apis/dictType/update.js +2 -2
- package/apis/email/config.js +4 -7
- package/apis/email/logList.js +2 -7
- package/apis/email/send.js +1 -2
- package/apis/email/verify.js +1 -3
- package/apis/loginLog/select.js +2 -7
- package/apis/menu/select.js +2 -7
- package/apis/operateLog/select.js +2 -7
- package/apis/role/apiSave.js +2 -2
- package/apis/role/menuSave.js +2 -2
- package/apis/role/select.js +2 -7
- package/apis/source/imageList.js +2 -5
- package/apis/tongJi/dailyReport.js +12 -13
- package/apis/tongJi/dailyReportSelect.js +1 -2
- package/apis/tongJi/dailyStats.js +1 -1
- package/apis/tongJi/dailyStatsDistribution.js +2 -2
- package/apis/tongJi/errorList.js +1 -2
- package/apis/tongJi/errorReport.js +1 -2
- package/apis/tongJi/projectDelete.js +1 -3
- package/apis/tongJi/projectSelect.js +2 -4
- package/apis/tongJi/projectUpdate.js +2 -2
- package/apis/upload/file.js +7 -5
- package/checks/api.js +43 -66
- package/checks/config.js +17 -12
- package/checks/corns.js +28 -46
- package/checks/field.js +18 -0
- package/checks/items.js +16 -60
- package/checks/menu.js +28 -39
- package/checks/table.js +106 -26
- package/checks/validation.js +13 -0
- package/configs/beflyConfig.json +6 -6
- package/configs/constConfig.js +2 -63
- package/exports.js +2 -0
- package/hooks/auth.js +11 -7
- package/hooks/parser.js +55 -59
- package/hooks/permission.js +1 -0
- package/hooks/rateLimit.js +25 -62
- package/hooks/validator.js +43 -31
- package/index.js +43 -344
- package/{lib → libs}/cacheHelper.js +3 -8
- package/libs/cron.js +60 -0
- package/libs/logger/index.js +1 -0
- package/libs/logger/logger.js +245 -0
- package/libs/logger/sanitize.js +115 -0
- package/{lib → libs/mysql}/dbHelper.js +100 -73
- package/{lib → libs/mysql}/dbParse.js +16 -9
- package/{lib → libs/mysql}/dbUtil.js +15 -32
- package/libs/mysql/error.js +29 -0
- package/libs/mysql/index.js +6 -0
- package/libs/mysql/is.js +29 -0
- package/libs/mysql/mysql.js +43 -0
- package/libs/mysql/sql/identifier.js +85 -0
- package/libs/mysql/sql/index.js +2 -0
- package/{lib → libs/mysql/sql}/sqlBuilder.js +2 -3
- package/libs/mysql/util.js +44 -0
- package/libs/redis/index.js +2 -0
- package/libs/redis/redis.js +204 -0
- package/libs/redis/redisError.js +8 -0
- package/libs/tableModel.js +72 -0
- package/libs/tool.js +33 -0
- package/libs/validator/compiler.js +248 -0
- package/libs/validator/index.js +10 -0
- package/libs/validator/parser.js +173 -0
- package/libs/validator/util.js +5 -0
- package/package.json +10 -8
- package/paths.js +2 -3
- package/plugins/cache.js +2 -1
- package/plugins/email.js +4 -4
- package/plugins/mysql.js +5 -15
- package/plugins/redis.js +4 -12
- package/router/api.js +14 -10
- package/router/root.js +14 -0
- package/router/static.js +3 -3
- package/schemas/api.json +99 -0
- package/schemas/config.json +255 -0
- package/schemas/corn.json +39 -0
- package/schemas/item.json +43 -0
- package/schemas/menu.json +44 -0
- package/schemas/table.json +80 -0
- package/scripts/syncDb/apply.js +87 -0
- package/scripts/syncDb/ddl.js +43 -0
- package/scripts/syncDb/index.js +175 -30
- package/scripts/syncDb/model.js +60 -0
- package/scripts/syncDb/plan.js +160 -0
- package/scripts/syncDb/preflight.js +98 -0
- package/scripts/syncDb/report.js +177 -162
- package/scripts/syncDb/snapshot.js +118 -0
- package/tables/admin.json +51 -53
- package/tables/api.json +28 -39
- package/tables/dailyReport.json +85 -73
- package/tables/dict.json +27 -39
- package/tables/dictType.json +20 -34
- package/tables/emailLog.json +49 -47
- package/tables/errorReport.json +86 -60
- package/tables/file.json +47 -50
- package/tables/loginLog.json +68 -55
- package/tables/menu.json +20 -34
- package/tables/operateLog.json +53 -47
- package/tables/project.json +18 -30
- package/tables/role.json +33 -37
- package/utils/cors.js +37 -41
- package/utils/deepMerge.js +3 -1
- package/utils/error.js +1 -56
- package/utils/id.js +44 -0
- package/utils/is.js +6 -243
- package/utils/response.js +12 -1
- package/utils/scanFiles.js +13 -4
- package/utils/scanSources.js +58 -20
- package/utils/util.js +11 -163
- package/apis/_apis.js +0 -20
- package/apis/auth/sendSmsCode.js +0 -24
- package/configs/regexpAlias.json +0 -55
- package/lib/connect.js +0 -119
- package/lib/logger.js +0 -430
- package/lib/redisHelper.js +0 -399
- package/lib/validator.js +0 -274
- package/lib/xmlParse.js +0 -149
- package/plugins/config.js +0 -13
- package/plugins/cron.js +0 -115
- package/plugins/logger.js +0 -17
- package/plugins/tool.js +0 -131
- package/plugins/xmlParse.js +0 -10
- package/schemas/config.js +0 -67
- package/scripts/syncDb/context.js +0 -120
- package/scripts/syncDb/diff.js +0 -279
- package/scripts/syncDb/transform.js +0 -113
- package/sql/befly.sql +0 -271
- package/utils/email.js +0 -3
- package/utils/fieldClear.js +0 -22
- package/utils/formatValidationIssues.js +0 -28
- package/utils/getClientIp.js +0 -47
- package/utils/loggerUtils.js +0 -196
- package/utils/regexpUtil.js +0 -52
- /package/{lib → libs}/smtpText.js +0 -0
package/tables/menu.json
CHANGED
|
@@ -1,47 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
"
|
|
3
|
-
"name": "ID",
|
|
4
|
-
"input": "integer",
|
|
5
|
-
"min": 1,
|
|
6
|
-
"max": null
|
|
7
|
-
},
|
|
1
|
+
{
|
|
2
|
+
"$tableName": "菜单表",
|
|
8
3
|
"name": {
|
|
9
4
|
"name": "菜单名称",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
5
|
+
"minValue": 2,
|
|
6
|
+
"maxValue": 50,
|
|
7
|
+
"paramType": "string",
|
|
8
|
+
"fieldType": "varchar",
|
|
9
|
+
"fieldDefault": ""
|
|
13
10
|
},
|
|
14
11
|
"path": {
|
|
15
12
|
"name": "路由路径",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
13
|
+
"minValue": 1,
|
|
14
|
+
"maxValue": 150,
|
|
15
|
+
"paramType": "string",
|
|
16
|
+
"fieldType": "varchar",
|
|
17
|
+
"fieldDefault": ""
|
|
19
18
|
},
|
|
20
19
|
"sort": {
|
|
21
20
|
"name": "排序",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
21
|
+
"maxValue": 9999,
|
|
22
|
+
"paramType": "integer",
|
|
23
|
+
"fieldType": "integer",
|
|
24
|
+
"fieldDefault": 0
|
|
24
25
|
},
|
|
25
26
|
"parentPath": {
|
|
26
27
|
"name": "父级路径",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"name": "状态(0=已删除,1=正常,2=禁用)",
|
|
32
|
-
"input": "enumInteger",
|
|
33
|
-
"check": "0|1|2"
|
|
34
|
-
},
|
|
35
|
-
"createdAt": {
|
|
36
|
-
"name": "创建时间",
|
|
37
|
-
"input": "number"
|
|
38
|
-
},
|
|
39
|
-
"updatedAt": {
|
|
40
|
-
"name": "更新时间",
|
|
41
|
-
"input": "number"
|
|
42
|
-
},
|
|
43
|
-
"deletedAt": {
|
|
44
|
-
"name": "删除时间",
|
|
45
|
-
"input": "number"
|
|
28
|
+
"maxValue": 200,
|
|
29
|
+
"paramType": "string",
|
|
30
|
+
"fieldType": "varchar",
|
|
31
|
+
"fieldDefault": ""
|
|
46
32
|
}
|
|
47
33
|
}
|
package/tables/operateLog.json
CHANGED
|
@@ -1,91 +1,97 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"name": "ID",
|
|
4
|
-
"input": "integer",
|
|
5
|
-
"min": 1,
|
|
6
|
-
"max": null
|
|
7
|
-
},
|
|
2
|
+
"$tableName": "操作日志表",
|
|
8
3
|
"adminId": {
|
|
9
4
|
"name": "管理员ID",
|
|
10
|
-
"
|
|
5
|
+
"paramType": "integer",
|
|
6
|
+
"fieldType": "integer",
|
|
7
|
+
"fieldDefault": 0
|
|
11
8
|
},
|
|
12
9
|
"username": {
|
|
13
10
|
"name": "用户名",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
11
|
+
"minValue": 1,
|
|
12
|
+
"maxValue": 50,
|
|
13
|
+
"paramType": "string",
|
|
14
|
+
"fieldType": "varchar",
|
|
15
|
+
"fieldDefault": ""
|
|
17
16
|
},
|
|
18
17
|
"nickname": {
|
|
19
18
|
"name": "昵称",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
19
|
+
"maxValue": 50,
|
|
20
|
+
"paramType": "string",
|
|
21
|
+
"fieldType": "varchar",
|
|
22
|
+
"fieldDefault": ""
|
|
22
23
|
},
|
|
23
24
|
"ip": {
|
|
24
25
|
"name": "操作IP",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
26
|
+
"maxValue": 50,
|
|
27
|
+
"paramType": "string",
|
|
28
|
+
"fieldType": "varchar",
|
|
29
|
+
"fieldDefault": ""
|
|
27
30
|
},
|
|
28
31
|
"module": {
|
|
29
32
|
"name": "操作模块",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
33
|
+
"maxValue": 50,
|
|
34
|
+
"paramType": "string",
|
|
35
|
+
"fieldType": "varchar",
|
|
36
|
+
"fieldDefault": ""
|
|
32
37
|
},
|
|
33
38
|
"action": {
|
|
34
39
|
"name": "操作类型",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
40
|
+
"maxValue": 50,
|
|
41
|
+
"paramType": "string",
|
|
42
|
+
"fieldType": "varchar",
|
|
43
|
+
"fieldDefault": ""
|
|
37
44
|
},
|
|
38
45
|
"method": {
|
|
39
46
|
"name": "请求方法",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
47
|
+
"maxValue": 10,
|
|
48
|
+
"paramType": "string",
|
|
49
|
+
"fieldType": "varchar",
|
|
50
|
+
"fieldDefault": ""
|
|
42
51
|
},
|
|
43
52
|
"path": {
|
|
44
53
|
"name": "请求路径",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
54
|
+
"maxValue": 200,
|
|
55
|
+
"paramType": "string",
|
|
56
|
+
"fieldType": "varchar",
|
|
57
|
+
"fieldDefault": ""
|
|
47
58
|
},
|
|
48
59
|
"params": {
|
|
49
60
|
"name": "请求参数",
|
|
50
|
-
"
|
|
61
|
+
"paramType": "string",
|
|
62
|
+
"fieldType": "text",
|
|
63
|
+
"fieldNullable": true
|
|
51
64
|
},
|
|
52
65
|
"result": {
|
|
53
66
|
"name": "操作结果",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
67
|
+
"maxValue": 1,
|
|
68
|
+
"paramType": "integer",
|
|
69
|
+
"fieldType": "integer",
|
|
70
|
+
"fieldDefault": 0
|
|
56
71
|
},
|
|
57
72
|
"response": {
|
|
58
73
|
"name": "响应内容",
|
|
59
|
-
"
|
|
74
|
+
"paramType": "string",
|
|
75
|
+
"fieldType": "text",
|
|
76
|
+
"fieldNullable": true
|
|
60
77
|
},
|
|
61
78
|
"duration": {
|
|
62
79
|
"name": "耗时毫秒",
|
|
63
|
-
"
|
|
80
|
+
"paramType": "integer",
|
|
81
|
+
"fieldType": "integer",
|
|
82
|
+
"fieldDefault": 0
|
|
64
83
|
},
|
|
65
84
|
"operateTime": {
|
|
66
85
|
"name": "操作时间",
|
|
67
|
-
"
|
|
86
|
+
"paramType": "integer",
|
|
87
|
+
"fieldType": "integer",
|
|
88
|
+
"fieldDefault": 0
|
|
68
89
|
},
|
|
69
90
|
"remark": {
|
|
70
91
|
"name": "备注",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"name": "状态(0=已删除,1=正常,2=禁用)",
|
|
76
|
-
"input": "enumInteger",
|
|
77
|
-
"check": "0|1|2"
|
|
78
|
-
},
|
|
79
|
-
"createdAt": {
|
|
80
|
-
"name": "创建时间",
|
|
81
|
-
"input": "number"
|
|
82
|
-
},
|
|
83
|
-
"updatedAt": {
|
|
84
|
-
"name": "更新时间",
|
|
85
|
-
"input": "number"
|
|
86
|
-
},
|
|
87
|
-
"deletedAt": {
|
|
88
|
-
"name": "删除时间",
|
|
89
|
-
"input": "number"
|
|
92
|
+
"maxValue": 500,
|
|
93
|
+
"paramType": "string",
|
|
94
|
+
"fieldType": "varchar",
|
|
95
|
+
"fieldDefault": ""
|
|
90
96
|
}
|
|
91
97
|
}
|
package/tables/project.json
CHANGED
|
@@ -1,42 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"max": null
|
|
2
|
+
"$tableName": "项目表",
|
|
3
|
+
"$tableIndexes": {
|
|
4
|
+
"uk_befly_project_code": "unique#code",
|
|
5
|
+
"idx_befly_project_state": "index#state"
|
|
7
6
|
},
|
|
8
7
|
"code": {
|
|
9
8
|
"name": "产品代号",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
9
|
+
"minValue": 1,
|
|
10
|
+
"maxValue": 100,
|
|
11
|
+
"paramType": "string",
|
|
12
|
+
"fieldType": "varchar",
|
|
13
|
+
"fieldDefault": ""
|
|
13
14
|
},
|
|
14
15
|
"name": {
|
|
15
16
|
"name": "产品名称",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"minValue": 1,
|
|
18
|
+
"maxValue": 100,
|
|
19
|
+
"paramType": "string",
|
|
20
|
+
"fieldType": "varchar",
|
|
21
|
+
"fieldDefault": ""
|
|
19
22
|
},
|
|
20
23
|
"sort": {
|
|
21
24
|
"name": "排序",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"name": "状态(0=已删除,1=正常,2=禁用)",
|
|
27
|
-
"input": "enumInteger",
|
|
28
|
-
"check": "0|1|2"
|
|
29
|
-
},
|
|
30
|
-
"createdAt": {
|
|
31
|
-
"name": "创建时间",
|
|
32
|
-
"input": "number"
|
|
33
|
-
},
|
|
34
|
-
"updatedAt": {
|
|
35
|
-
"name": "更新时间",
|
|
36
|
-
"input": "number"
|
|
37
|
-
},
|
|
38
|
-
"deletedAt": {
|
|
39
|
-
"name": "删除时间",
|
|
40
|
-
"input": "number"
|
|
25
|
+
"maxValue": 9999,
|
|
26
|
+
"paramType": "integer",
|
|
27
|
+
"fieldType": "integer",
|
|
28
|
+
"fieldDefault": 0
|
|
41
29
|
}
|
|
42
30
|
}
|
package/tables/role.json
CHANGED
|
@@ -1,56 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
"
|
|
3
|
-
"name": "ID",
|
|
4
|
-
"input": "integer",
|
|
5
|
-
"min": 1,
|
|
6
|
-
"max": null
|
|
7
|
-
},
|
|
1
|
+
{
|
|
2
|
+
"$tableName": "角色表",
|
|
8
3
|
"name": {
|
|
9
4
|
"name": "角色名称",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
5
|
+
"minValue": 2,
|
|
6
|
+
"maxValue": 50,
|
|
7
|
+
"paramType": "string",
|
|
8
|
+
"fieldType": "varchar",
|
|
9
|
+
"fieldDefault": ""
|
|
13
10
|
},
|
|
14
11
|
"code": {
|
|
15
12
|
"name": "角色编码",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
13
|
+
"minValue": 2,
|
|
14
|
+
"maxValue": 50,
|
|
15
|
+
"paramType": "string",
|
|
16
|
+
"pattern": "^[a-zA-Z0-9_-]+$",
|
|
17
|
+
"fieldType": "varchar",
|
|
18
|
+
"fieldDefault": ""
|
|
20
19
|
},
|
|
21
20
|
"description": {
|
|
22
21
|
"name": "角色描述",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
22
|
+
"maxValue": 200,
|
|
23
|
+
"paramType": "string",
|
|
24
|
+
"fieldType": "varchar",
|
|
25
|
+
"fieldDefault": ""
|
|
25
26
|
},
|
|
26
27
|
"menus": {
|
|
27
28
|
"name": "菜单权限",
|
|
28
|
-
"
|
|
29
|
+
"paramType": "array",
|
|
30
|
+
"items": {
|
|
31
|
+
"paramType": "string"
|
|
32
|
+
},
|
|
33
|
+
"fieldType": "text",
|
|
34
|
+
"fieldNullable": true
|
|
29
35
|
},
|
|
30
36
|
"apis": {
|
|
31
37
|
"name": "接口权限",
|
|
32
|
-
"
|
|
38
|
+
"paramType": "array",
|
|
39
|
+
"items": {
|
|
40
|
+
"paramType": "string"
|
|
41
|
+
},
|
|
42
|
+
"fieldType": "text",
|
|
43
|
+
"fieldNullable": true
|
|
33
44
|
},
|
|
34
45
|
"sort": {
|
|
35
46
|
"name": "排序",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"name": "状态(0=已删除,1=正常,2=禁用)",
|
|
41
|
-
"input": "enumInteger",
|
|
42
|
-
"check": "0|1|2"
|
|
43
|
-
},
|
|
44
|
-
"createdAt": {
|
|
45
|
-
"name": "创建时间",
|
|
46
|
-
"input": "number"
|
|
47
|
-
},
|
|
48
|
-
"updatedAt": {
|
|
49
|
-
"name": "更新时间",
|
|
50
|
-
"input": "number"
|
|
51
|
-
},
|
|
52
|
-
"deletedAt": {
|
|
53
|
-
"name": "删除时间",
|
|
54
|
-
"input": "number"
|
|
47
|
+
"maxValue": 9999,
|
|
48
|
+
"paramType": "integer",
|
|
49
|
+
"fieldType": "integer",
|
|
50
|
+
"fieldDefault": 0
|
|
55
51
|
}
|
|
56
52
|
}
|
package/utils/cors.js
CHANGED
|
@@ -1,52 +1,48 @@
|
|
|
1
|
+
const originMatcherCache = new WeakMap();
|
|
2
|
+
|
|
3
|
+
function getOriginMatchers(config) {
|
|
4
|
+
if (originMatcherCache.has(config)) return originMatcherCache.get(config);
|
|
5
|
+
const matchers = config.origins?.map((pattern) => new Bun.Glob(pattern));
|
|
6
|
+
originMatcherCache.set(config, matchers);
|
|
7
|
+
return matchers;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function splitHeaderList(value) {
|
|
11
|
+
return value
|
|
12
|
+
.split(",")
|
|
13
|
+
.map((item) => item.trim())
|
|
14
|
+
.filter(Boolean);
|
|
15
|
+
}
|
|
16
|
+
|
|
1
17
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* @param config - CORS 配置
|
|
5
|
-
* @returns CORS 响应头对象
|
|
18
|
+
* origins 省略时回显任意 Origin;配置后使用 Bun.Glob 匹配 Origin。
|
|
19
|
+
* 无 Origin 的 VS Code、小程序、App、服务端请求不受浏览器 CORS 限制。
|
|
6
20
|
*/
|
|
7
21
|
export function setCorsOptions(req, config) {
|
|
8
22
|
const origin = req.headers.get("origin");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const key = value.toLowerCase();
|
|
26
|
-
if (allowedHeaderMap[key]) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
allowedHeaderMap[key] = 1;
|
|
31
|
-
allowedHeaderItems.push(value);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
for (const item of String(config.allowedHeaders || "").split(",")) {
|
|
35
|
-
pushHeaderIfNeeded(item);
|
|
23
|
+
if (!origin) return {};
|
|
24
|
+
|
|
25
|
+
const originMatchers = getOriginMatchers(config);
|
|
26
|
+
const unrestricted = originMatchers === undefined;
|
|
27
|
+
if (!unrestricted && !originMatchers.some((matcher) => matcher.match(origin))) return { Vary: "Origin" };
|
|
28
|
+
|
|
29
|
+
const requestedHeaders = splitHeaderList(req.headers.get("access-control-request-headers") || "");
|
|
30
|
+
let responseHeaders;
|
|
31
|
+
if (unrestricted) {
|
|
32
|
+
responseHeaders = requestedHeaders.length > 0 ? requestedHeaders : splitHeaderList(config.allowedHeaders);
|
|
33
|
+
} else {
|
|
34
|
+
const allowedHeaders = splitHeaderList(config.allowedHeaders);
|
|
35
|
+
const allowedHeaderSet = new Set(allowedHeaders.map((item) => item.toLowerCase()));
|
|
36
|
+
responseHeaders = requestedHeaders.length > 0 ? requestedHeaders.filter((item) => allowedHeaderSet.has(item.toLowerCase())) : allowedHeaders;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
for (const item of String(requestedHeaders).split(",")) {
|
|
39
|
-
pushHeaderIfNeeded(item);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const allowHeaders = allowedHeaderItems.join(", ");
|
|
43
|
-
|
|
44
39
|
return {
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"Access-Control-Allow-
|
|
40
|
+
"Access-Control-Allow-Origin": origin,
|
|
41
|
+
Vary: "Origin",
|
|
42
|
+
"Access-Control-Allow-Methods": "GET,POST",
|
|
43
|
+
"Access-Control-Allow-Headers": responseHeaders.join(", "),
|
|
48
44
|
"Access-Control-Expose-Headers": config.exposedHeaders,
|
|
49
45
|
"Access-Control-Max-Age": String(config.maxAge),
|
|
50
|
-
"Access-Control-Allow-Credentials":
|
|
46
|
+
...(config.credentials ? { "Access-Control-Allow-Credentials": "true" } : {})
|
|
51
47
|
};
|
|
52
48
|
}
|
package/utils/deepMerge.js
CHANGED
|
@@ -22,7 +22,9 @@ function concat(targetArr, sourceArr, cloneTargetItems) {
|
|
|
22
22
|
nextArr.push(clone(item));
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const merged = nextArr;
|
|
26
|
+
if (merged.every((item) => item === null || ["string", "number", "boolean"].includes(typeof item))) return [...new Set(merged)];
|
|
27
|
+
return merged;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
function mergeValue(baseValue, incomingValue) {
|
package/utils/error.js
CHANGED
|
@@ -1,64 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 统一错误工厂
|
|
3
|
-
* 框架错误对象的唯一构造入口,统一字段约定:
|
|
4
|
-
* - code: "validation" | "runtime" | "policy"
|
|
5
|
-
* - subsystem: 子系统标识(sql/cache/redis/sync/config/start/...)
|
|
6
|
-
* - operation: 操作名
|
|
7
|
-
* - 其余字段原样透传(如 table、roleCode、runMode 等)
|
|
8
|
-
* - 不传 cause 时不设置(缺省为 undefined,避免 cause: null 噪音)
|
|
9
|
-
*/
|
|
10
1
|
export function createError(message, options = {}) {
|
|
11
2
|
const error = new Error(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
12
3
|
|
|
13
|
-
if (options.code) error.code = options.code;
|
|
14
|
-
if (options.subsystem) error.subsystem = options.subsystem;
|
|
15
|
-
if (options.operation) error.operation = options.operation;
|
|
16
|
-
|
|
17
4
|
for (const [key, value] of Object.entries(options)) {
|
|
18
|
-
if (key
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
error[key] = value;
|
|
5
|
+
if (key !== "cause") error[key] = value;
|
|
22
6
|
}
|
|
23
7
|
|
|
24
8
|
return error;
|
|
25
9
|
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 参数校验错误(code: "validation")
|
|
29
|
-
*/
|
|
30
|
-
export function validationError(message) {
|
|
31
|
-
return createError(message, { code: "validation" });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 沿 cause 链取最底层错误(根因)
|
|
36
|
-
*/
|
|
37
|
-
export function getRootCause(error) {
|
|
38
|
-
let current = error;
|
|
39
|
-
while (current?.cause instanceof Error) {
|
|
40
|
-
current = current.cause;
|
|
41
|
-
}
|
|
42
|
-
return current;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 错误链摘要:沿 cause 展开为单行文本,根因在后
|
|
47
|
-
* 每层格式:message [code/subsystem/operation](无元信息时仅 message)
|
|
48
|
-
* 例:SQL执行失败 [runtime/sql/execute] <- ER_DUP_ENTRY: 重复插入 [runtime]
|
|
49
|
-
*/
|
|
50
|
-
export function errorChainSummary(error) {
|
|
51
|
-
const parts = [];
|
|
52
|
-
const visited = new Set();
|
|
53
|
-
let current = error;
|
|
54
|
-
|
|
55
|
-
while (current instanceof Error && !visited.has(current)) {
|
|
56
|
-
visited.add(current);
|
|
57
|
-
const meta = [current.code, current.subsystem, current.operation].filter(Boolean).join("/");
|
|
58
|
-
const text = current.message || current.name || "Error";
|
|
59
|
-
parts.push(meta ? `${text} [${meta}]` : text);
|
|
60
|
-
current = current.cause;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return parts.join(" <- ");
|
|
64
|
-
}
|
package/utils/id.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function resolveInstanceId(value) {
|
|
2
|
+
const instanceId = value === undefined || value === "" ? 0 : Number(value);
|
|
3
|
+
if (!Number.isInteger(instanceId) || instanceId < 0 || instanceId > 9) {
|
|
4
|
+
throw new TypeError(`BM2_INSTANCE_ID 必须是 0 到 9 的整数,当前值: ${String(value)}`);
|
|
5
|
+
}
|
|
6
|
+
return instanceId;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 创建 13 位逻辑毫秒 + 1 位 BM2 实例编号 + 2 位序列的安全整数 ID 生成器。
|
|
11
|
+
*/
|
|
12
|
+
export function createIdGenerator(options = {}) {
|
|
13
|
+
const instanceId = resolveInstanceId(options.instanceId ?? Bun.env.BM2_INSTANCE_ID);
|
|
14
|
+
const now = options.now || Date.now;
|
|
15
|
+
let lastTimestamp = 0;
|
|
16
|
+
let sequence = 0;
|
|
17
|
+
|
|
18
|
+
return function generateId() {
|
|
19
|
+
const currentTimestamp = now();
|
|
20
|
+
if (!Number.isInteger(currentTimestamp) || currentTimestamp <= 0) {
|
|
21
|
+
throw new TypeError(`当前时间戳必须是正整数,当前值: ${String(currentTimestamp)}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (currentTimestamp > lastTimestamp) {
|
|
25
|
+
lastTimestamp = currentTimestamp;
|
|
26
|
+
sequence = 0;
|
|
27
|
+
} else {
|
|
28
|
+
sequence += 1;
|
|
29
|
+
if (sequence > 99) {
|
|
30
|
+
lastTimestamp += 1;
|
|
31
|
+
sequence = 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const id = lastTimestamp * 1000 + instanceId * 100 + sequence;
|
|
36
|
+
if (!Number.isSafeInteger(id)) throw new RangeError(`生成的 ID 超出 JavaScript 安全整数范围: ${id}`);
|
|
37
|
+
return id;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 使用当前 Bun 进程的 BM2_INSTANCE_ID 生成全局唯一的安全整数 ID。
|
|
43
|
+
*/
|
|
44
|
+
export const genId = createIdGenerator();
|