befly 3.0.0 → 3.0.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/checks/conflict.ts +35 -114
- package/checks/table.ts +31 -63
- package/config/env.ts +3 -3
- package/config/fields.ts +55 -0
- package/config/regexAliases.ts +51 -0
- package/config/reserved.ts +1 -1
- package/main.ts +17 -71
- package/package.json +7 -28
- package/plugins/db.ts +11 -10
- package/plugins/redis.ts +5 -9
- package/scripts/syncDb/apply.ts +3 -3
- package/scripts/syncDb/constants.ts +2 -1
- package/scripts/syncDb/ddl.ts +15 -8
- package/scripts/syncDb/helpers.ts +3 -2
- package/scripts/syncDb/index.ts +23 -35
- package/scripts/syncDb/state.ts +8 -6
- package/scripts/syncDb/table.ts +32 -22
- package/scripts/syncDb/tableCreate.ts +9 -3
- package/scripts/syncDb/tests/constants.test.ts +2 -1
- package/scripts/syncDb.ts +10 -9
- package/types/addon.d.ts +53 -0
- package/types/api.d.ts +17 -14
- package/types/befly.d.ts +2 -6
- package/types/context.d.ts +7 -0
- package/types/database.d.ts +9 -14
- package/types/index.d.ts +442 -8
- package/types/index.ts +35 -56
- package/types/redis.d.ts +2 -0
- package/types/validator.d.ts +0 -2
- package/types/validator.ts +43 -0
- package/utils/colors.ts +117 -37
- package/utils/database.ts +348 -0
- package/utils/dbHelper.ts +687 -116
- package/utils/helper.ts +812 -0
- package/utils/index.ts +10 -23
- package/utils/logger.ts +78 -171
- package/utils/redisHelper.ts +135 -152
- package/{types/context.ts → utils/requestContext.ts} +3 -3
- package/utils/sqlBuilder.ts +142 -165
- package/utils/validate.ts +51 -9
- package/apis/health/info.ts +0 -64
- package/apis/tool/tokenCheck.ts +0 -51
- package/bin/befly.ts +0 -202
- package/bunfig.toml +0 -3
- package/plugins/tool.ts +0 -34
- package/scripts/syncDev.ts +0 -112
- package/system.ts +0 -149
- package/tables/_common.json +0 -21
- package/tables/admin.json +0 -10
- package/utils/addonHelper.ts +0 -60
- package/utils/api.ts +0 -23
- package/utils/datetime.ts +0 -51
- package/utils/errorHandler.ts +0 -68
- package/utils/objectHelper.ts +0 -68
- package/utils/pluginHelper.ts +0 -62
- package/utils/response.ts +0 -38
- package/utils/sqlHelper.ts +0 -447
- package/utils/tableHelper.ts +0 -167
- package/utils/tool.ts +0 -230
- package/utils/typeHelper.ts +0 -101
package/scripts/syncDb/table.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Logger } from '../../utils/logger.js';
|
|
11
|
-
import {
|
|
11
|
+
import { toSnakeCase } from '../../utils/helper.js';
|
|
12
|
+
import { parseRule } from '../../utils/helper.js';
|
|
12
13
|
import { IS_MYSQL, IS_PG, IS_SQLITE, SYSTEM_INDEX_FIELDS, CHANGE_TYPE_LABELS, typeMapping } from './constants.js';
|
|
13
14
|
import { quoteIdentifier, logFieldChange, resolveDefaultValue, generateDefaultSql, isStringOrArrayType, getSqlType } from './helpers.js';
|
|
14
15
|
import { buildIndexSQL, generateDDLClause, isPgCompatibleTypeChange } from './ddl.js';
|
|
@@ -56,13 +57,16 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
56
57
|
const indexActions = [];
|
|
57
58
|
|
|
58
59
|
for (const [fieldKey, fieldRule] of Object.entries(fields)) {
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
// 转换字段名为下划线格式(用于与数据库字段对比)
|
|
61
|
+
const dbFieldName = toSnakeCase(fieldKey);
|
|
62
|
+
|
|
63
|
+
if (existingColumns[dbFieldName]) {
|
|
64
|
+
const comparison = compareFieldDefinition(existingColumns[dbFieldName], fieldRule, dbFieldName);
|
|
61
65
|
if (comparison.length > 0) {
|
|
62
66
|
for (const c of comparison) {
|
|
63
67
|
// 使用统一的日志格式函数和常量标签
|
|
64
68
|
const changeLabel = CHANGE_TYPE_LABELS[c.type] || '未知';
|
|
65
|
-
logFieldChange(tableName,
|
|
69
|
+
logFieldChange(tableName, dbFieldName, c.type, c.current, c.expected, changeLabel);
|
|
66
70
|
|
|
67
71
|
// 全量计数:全局累加
|
|
68
72
|
if (c.type === 'datatype') globalCount.typeChanges++;
|
|
@@ -74,9 +78,9 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
74
78
|
const parsed = parseRule(fieldRule);
|
|
75
79
|
const { name: fieldName, type: fieldType, max: fieldMax, default: fieldDefault } = parsed;
|
|
76
80
|
|
|
77
|
-
if (isStringOrArrayType(fieldType) && existingColumns[
|
|
78
|
-
if (existingColumns[
|
|
79
|
-
Logger.warn(`[跳过危险变更] ${tableName}.${
|
|
81
|
+
if (isStringOrArrayType(fieldType) && existingColumns[dbFieldName].length) {
|
|
82
|
+
if (existingColumns[dbFieldName].length! > fieldMax) {
|
|
83
|
+
Logger.warn(`[跳过危险变更] ${tableName}.${dbFieldName} 长度收缩 ${existingColumns[dbFieldName].length} -> ${fieldMax} 已被跳过(设置 SYNC_DISALLOW_SHRINK=0 可放开)`);
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
|
|
@@ -87,9 +91,9 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
87
91
|
|
|
88
92
|
// 严格限制:除 string/array 互转外,禁止任何字段类型变更;一旦发现,立即终止同步
|
|
89
93
|
if (hasTypeChange) {
|
|
90
|
-
const currentSqlType = String(existingColumns[
|
|
94
|
+
const currentSqlType = String(existingColumns[dbFieldName].type || '').toLowerCase();
|
|
91
95
|
const newSqlType = String(typeMapping[fieldType] || '').toLowerCase();
|
|
92
|
-
const errorMsg = [`禁止字段类型变更: ${tableName}.${
|
|
96
|
+
const errorMsg = [`禁止字段类型变更: ${tableName}.${dbFieldName}`, `当前类型: ${currentSqlType}`, `目标类型: ${newSqlType}`, `说明: 仅允许 string<->array 互相切换,其他类型变更需要手动处理`].join('\n');
|
|
93
97
|
throw new Error(errorMsg);
|
|
94
98
|
}
|
|
95
99
|
|
|
@@ -108,11 +112,11 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
108
112
|
|
|
109
113
|
if (v !== null && v !== '') {
|
|
110
114
|
if (IS_PG) {
|
|
111
|
-
defaultClauses.push(`ALTER COLUMN "${
|
|
115
|
+
defaultClauses.push(`ALTER COLUMN "${dbFieldName}" SET DEFAULT ${v}`);
|
|
112
116
|
} else if (IS_MYSQL && onlyDefaultChanged) {
|
|
113
117
|
// MySQL 的 TEXT/BLOB 不允许 DEFAULT,跳过 text 类型
|
|
114
118
|
if (fieldType !== 'text') {
|
|
115
|
-
defaultClauses.push(`ALTER COLUMN \`${
|
|
119
|
+
defaultClauses.push(`ALTER COLUMN \`${dbFieldName}\` SET DEFAULT ${v}`);
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
}
|
|
@@ -121,15 +125,15 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
121
125
|
// 若不仅仅是默认值变化,继续生成修改子句
|
|
122
126
|
if (!onlyDefaultChanged) {
|
|
123
127
|
let skipModify = false;
|
|
124
|
-
if (hasLengthChange && isStringOrArrayType(fieldType) && existingColumns[
|
|
125
|
-
const oldLen = existingColumns[
|
|
128
|
+
if (hasLengthChange && isStringOrArrayType(fieldType) && existingColumns[dbFieldName].length) {
|
|
129
|
+
const oldLen = existingColumns[dbFieldName].length!;
|
|
126
130
|
const isShrink = oldLen > fieldMax;
|
|
127
131
|
if (isShrink) skipModify = true;
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
if (hasTypeChange) {
|
|
131
|
-
if (IS_PG && isPgCompatibleTypeChange(existingColumns[
|
|
132
|
-
Logger.info(`[PG兼容类型变更] ${tableName}.${
|
|
135
|
+
if (IS_PG && isPgCompatibleTypeChange(existingColumns[dbFieldName].type, typeMapping[fieldType].toLowerCase())) {
|
|
136
|
+
Logger.info(`[PG兼容类型变更] ${tableName}.${dbFieldName} ${existingColumns[dbFieldName].type} -> ${typeMapping[fieldType].toLowerCase()} 允许执行`);
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
|
|
@@ -141,7 +145,7 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
141
145
|
const parsed = parseRule(fieldRule);
|
|
142
146
|
const { name: fieldName, type: fieldType, max: fieldMax, default: fieldDefault } = parsed;
|
|
143
147
|
const lenPart = isStringOrArrayType(fieldType) ? ` 长度:${parseInt(String(fieldMax))}` : '';
|
|
144
|
-
Logger.info(`[新增字段] ${tableName}.${
|
|
148
|
+
Logger.info(`[新增字段] ${tableName}.${dbFieldName} 类型:${fieldType}${lenPart} 默认:${fieldDefault ?? 'NULL'}`);
|
|
145
149
|
addClauses.push(generateDDLClause(fieldKey, fieldRule, true));
|
|
146
150
|
changed = true;
|
|
147
151
|
globalCount.addFields++;
|
|
@@ -160,14 +164,17 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
160
164
|
|
|
161
165
|
// 检查业务字段索引
|
|
162
166
|
for (const [fieldKey, fieldRule] of Object.entries(fields)) {
|
|
167
|
+
// 转换字段名为下划线格式
|
|
168
|
+
const dbFieldName = toSnakeCase(fieldKey);
|
|
169
|
+
|
|
163
170
|
const parsed = parseRule(fieldRule);
|
|
164
|
-
const indexName = `idx_${
|
|
171
|
+
const indexName = `idx_${dbFieldName}`;
|
|
165
172
|
if (parsed.index === 1 && !existingIndexes[indexName]) {
|
|
166
|
-
indexActions.push({ action: 'create', indexName, fieldName:
|
|
173
|
+
indexActions.push({ action: 'create', indexName, fieldName: dbFieldName });
|
|
167
174
|
changed = true;
|
|
168
175
|
globalCount.indexCreate++;
|
|
169
176
|
} else if (!(parsed.index === 1) && existingIndexes[indexName] && existingIndexes[indexName].length === 1) {
|
|
170
|
-
indexActions.push({ action: 'drop', indexName, fieldName:
|
|
177
|
+
indexActions.push({ action: 'drop', indexName, fieldName: dbFieldName });
|
|
171
178
|
changed = true;
|
|
172
179
|
globalCount.indexDrop++;
|
|
173
180
|
}
|
|
@@ -177,13 +184,16 @@ export async function modifyTable(sql: SQL, tableName: string, fields: Record<st
|
|
|
177
184
|
const commentActions = [];
|
|
178
185
|
if (IS_PG) {
|
|
179
186
|
for (const [fieldKey, fieldRule] of Object.entries(fields)) {
|
|
180
|
-
|
|
187
|
+
// 转换字段名为下划线格式
|
|
188
|
+
const dbFieldName = toSnakeCase(fieldKey);
|
|
189
|
+
|
|
190
|
+
if (existingColumns[dbFieldName]) {
|
|
181
191
|
const parsed = parseRule(fieldRule);
|
|
182
192
|
const { name: fieldName } = parsed;
|
|
183
|
-
const curr = existingColumns[
|
|
193
|
+
const curr = existingColumns[dbFieldName].comment || '';
|
|
184
194
|
const want = fieldName && fieldName !== 'null' ? String(fieldName) : '';
|
|
185
195
|
if (want !== curr) {
|
|
186
|
-
commentActions.push(`COMMENT ON COLUMN "${tableName}"."${
|
|
196
|
+
commentActions.push(`COMMENT ON COLUMN "${tableName}"."${dbFieldName}" IS ${want ? `'${want}'` : 'NULL'}`);
|
|
187
197
|
changed = true;
|
|
188
198
|
}
|
|
189
199
|
}
|
|
@@ -13,7 +13,7 @@ import { Logger } from '../../utils/logger.js';
|
|
|
13
13
|
import { IS_MYSQL, IS_PG, MYSQL_TABLE_CONFIG } from './constants.js';
|
|
14
14
|
import { quoteIdentifier } from './helpers.js';
|
|
15
15
|
import { buildSystemColumnDefs, buildBusinessColumnDefs, buildIndexSQL } from './ddl.js';
|
|
16
|
-
import { parseRule } from '../../utils/
|
|
16
|
+
import { parseRule, toSnakeCase } from '../../utils/helper.js';
|
|
17
17
|
import type { SQL } from 'bun';
|
|
18
18
|
|
|
19
19
|
// 是否为计划模式(从环境变量读取)
|
|
@@ -47,9 +47,12 @@ async function addPostgresComments(sql: SQL, tableName: string, fields: Record<s
|
|
|
47
47
|
|
|
48
48
|
// 业务字段注释
|
|
49
49
|
for (const [fieldKey, fieldRule] of Object.entries(fields)) {
|
|
50
|
+
// 转换字段名为下划线格式
|
|
51
|
+
const dbFieldName = toSnakeCase(fieldKey);
|
|
52
|
+
|
|
50
53
|
const parsed = parseRule(fieldRule);
|
|
51
54
|
const { name: fieldName } = parsed;
|
|
52
|
-
const stmt = `COMMENT ON COLUMN "${tableName}"."${
|
|
55
|
+
const stmt = `COMMENT ON COLUMN "${tableName}"."${dbFieldName}" IS '${fieldName}'`;
|
|
53
56
|
if (IS_PLAN) {
|
|
54
57
|
Logger.info(`[计划] ${stmt}`);
|
|
55
58
|
} else {
|
|
@@ -81,9 +84,12 @@ async function createTableIndexes(sql: SQL, tableName: string, fields: Record<st
|
|
|
81
84
|
|
|
82
85
|
// 业务字段索引
|
|
83
86
|
for (const [fieldKey, fieldRule] of Object.entries(fields)) {
|
|
87
|
+
// 转换字段名为下划线格式
|
|
88
|
+
const dbFieldName = toSnakeCase(fieldKey);
|
|
89
|
+
|
|
84
90
|
const parsed = parseRule(fieldRule);
|
|
85
91
|
if (parsed.index === 1) {
|
|
86
|
-
const stmt = buildIndexSQL(tableName, `idx_${
|
|
92
|
+
const stmt = buildIndexSQL(tableName, `idx_${dbFieldName}`, dbFieldName, 'create');
|
|
87
93
|
if (IS_PLAN) {
|
|
88
94
|
Logger.info(`[计划] ${stmt}`);
|
|
89
95
|
} else {
|
|
@@ -82,7 +82,8 @@ describe('syncDb/constants', () => {
|
|
|
82
82
|
expect(typeMapping.number).toBeDefined();
|
|
83
83
|
expect(typeMapping.string).toBeDefined();
|
|
84
84
|
expect(typeMapping.text).toBeDefined();
|
|
85
|
-
expect(typeMapping.
|
|
85
|
+
expect(typeMapping.array_string).toBeDefined();
|
|
86
|
+
expect(typeMapping.array_text).toBeDefined();
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
test('不同数据库的类型映射应不同', () => {
|
package/scripts/syncDb.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { SyncDb } from './syncDb/index.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
1
|
+
import { SyncDb } from './syncDb/index.js';
|
|
2
|
+
import { Logger } from '../utils/logger.js';
|
|
3
|
+
|
|
4
|
+
// 如果直接运行此脚本
|
|
5
|
+
if (import.meta.main) {
|
|
6
|
+
SyncDb().catch((error) => {
|
|
7
|
+
Logger.error('数据库同步失败', error);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
});
|
|
10
|
+
}
|
package/types/addon.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Addon 配置类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Addon 作者信息
|
|
7
|
+
*/
|
|
8
|
+
export interface AddonAuthor {
|
|
9
|
+
/** 作者名称 */
|
|
10
|
+
name: string;
|
|
11
|
+
/** 作者邮箱 */
|
|
12
|
+
email?: string;
|
|
13
|
+
/** 作者网站 */
|
|
14
|
+
url?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Addon 配置
|
|
19
|
+
*/
|
|
20
|
+
export interface AddonConfig {
|
|
21
|
+
/** Addon 唯一标识(小写、短横线或下划线),例如 "admin"、"demo" */
|
|
22
|
+
name: string;
|
|
23
|
+
|
|
24
|
+
/** Addon 人类可读名称,例如 "管理后台" */
|
|
25
|
+
title: string;
|
|
26
|
+
|
|
27
|
+
/** 版本号(语义化版本),例如 "1.0.0" */
|
|
28
|
+
version?: string;
|
|
29
|
+
|
|
30
|
+
/** 简短描述 */
|
|
31
|
+
description?: string;
|
|
32
|
+
|
|
33
|
+
/** 作者信息 */
|
|
34
|
+
author?: AddonAuthor | string;
|
|
35
|
+
|
|
36
|
+
/** 源码仓库链接 */
|
|
37
|
+
repo?: string;
|
|
38
|
+
|
|
39
|
+
/** 关键词(用于搜索和分类) */
|
|
40
|
+
keywords?: string[];
|
|
41
|
+
|
|
42
|
+
/** 主入口文件路径(相对于 addon 目录),例如 "index.ts" */
|
|
43
|
+
entry?: string;
|
|
44
|
+
|
|
45
|
+
/** 是否默认启用 */
|
|
46
|
+
enabled?: boolean;
|
|
47
|
+
|
|
48
|
+
/** 依赖的其他 addon 或核心包 */
|
|
49
|
+
dependencies?: Record<string, string>;
|
|
50
|
+
|
|
51
|
+
/** 许可证 */
|
|
52
|
+
license?: string;
|
|
53
|
+
}
|
package/types/api.d.ts
CHANGED
|
@@ -99,26 +99,29 @@ export interface ApiOptions {
|
|
|
99
99
|
* API 路由配置
|
|
100
100
|
*/
|
|
101
101
|
export interface ApiRoute<T = any, R = any> {
|
|
102
|
-
/**
|
|
103
|
-
method: HttpMethod;
|
|
104
|
-
|
|
105
|
-
/** 接口名称 */
|
|
102
|
+
/** 接口名称(必填) */
|
|
106
103
|
name: string;
|
|
107
104
|
|
|
108
|
-
/**
|
|
109
|
-
|
|
105
|
+
/** 处理器函数(必填) */
|
|
106
|
+
handler: ApiHandler<T, R>;
|
|
110
107
|
|
|
111
|
-
/**
|
|
112
|
-
|
|
108
|
+
/** HTTP 方法(可选,默认 POST) */
|
|
109
|
+
method?: HttpMethod;
|
|
113
110
|
|
|
114
|
-
/**
|
|
115
|
-
|
|
111
|
+
/** 认证类型(可选,默认 true)
|
|
112
|
+
* - true: 需要登录
|
|
113
|
+
* - false: 公开访问(无需登录)
|
|
114
|
+
*/
|
|
115
|
+
auth?: boolean;
|
|
116
116
|
|
|
117
|
-
/**
|
|
118
|
-
|
|
117
|
+
/** 字段定义(验证规则)(可选,默认 {}) */
|
|
118
|
+
fields?: TableDefinition;
|
|
119
119
|
|
|
120
|
-
/**
|
|
121
|
-
|
|
120
|
+
/** 必填字段(可选,默认 []) */
|
|
121
|
+
required?: string[];
|
|
122
|
+
|
|
123
|
+
/** 路由路径(运行时生成) */
|
|
124
|
+
route?: string;
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
/**
|
package/types/befly.d.ts
CHANGED
|
@@ -8,9 +8,8 @@ import type { KeyValue } from './common.js';
|
|
|
8
8
|
import type { Logger } from '../utils/logger.js';
|
|
9
9
|
import type { Jwt } from '../utils/jwt.js';
|
|
10
10
|
import type { Validator } from '../utils/validate.js';
|
|
11
|
-
import type {
|
|
11
|
+
import type { DbHelper } from '../utils/dbHelper.js';
|
|
12
12
|
import type { Crypto2 } from '../utils/crypto.js';
|
|
13
|
-
import type { Tool } from '../utils/tool.js';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* Befly 应用选项
|
|
@@ -79,14 +78,11 @@ export interface Befly {
|
|
|
79
78
|
validator: Validator;
|
|
80
79
|
|
|
81
80
|
/** SQL 管理器 */
|
|
82
|
-
sql:
|
|
81
|
+
sql: DbHelper;
|
|
83
82
|
|
|
84
83
|
/** 加密工具 */
|
|
85
84
|
crypto: Crypto2;
|
|
86
85
|
|
|
87
|
-
/** 通用工具 */
|
|
88
|
-
tool: Tool;
|
|
89
|
-
|
|
90
86
|
/** 数据库连接 */
|
|
91
87
|
db: any;
|
|
92
88
|
|
package/types/database.d.ts
CHANGED
|
@@ -17,16 +17,12 @@ export interface QueryOptions {
|
|
|
17
17
|
fields?: string[];
|
|
18
18
|
/** WHERE 条件 */
|
|
19
19
|
where?: WhereConditions;
|
|
20
|
-
/**
|
|
21
|
-
orderBy?: string;
|
|
20
|
+
/** 排序(格式:["字段#ASC", "字段#DESC"]) */
|
|
21
|
+
orderBy?: string[];
|
|
22
22
|
/** 页码(从 1 开始) */
|
|
23
23
|
page?: number;
|
|
24
24
|
/** 每页数量 */
|
|
25
25
|
limit?: number;
|
|
26
|
-
/** 是否包含已删除数据 */
|
|
27
|
-
includeDeleted?: boolean;
|
|
28
|
-
/** 自定义 state 条件 */
|
|
29
|
-
customState?: WhereConditions;
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
/**
|
|
@@ -49,8 +45,6 @@ export interface UpdateOptions {
|
|
|
49
45
|
data: Record<string, any>;
|
|
50
46
|
/** WHERE 条件 */
|
|
51
47
|
where: WhereConditions;
|
|
52
|
-
/** 是否包含已删除数据 */
|
|
53
|
-
includeDeleted?: boolean;
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
/**
|
|
@@ -61,8 +55,6 @@ export interface DeleteOptions {
|
|
|
61
55
|
table: string;
|
|
62
56
|
/** WHERE 条件 */
|
|
63
57
|
where: WhereConditions;
|
|
64
|
-
/** 是否物理删除(false=软删除,true=物理删除) */
|
|
65
|
-
hard?: boolean;
|
|
66
58
|
}
|
|
67
59
|
|
|
68
60
|
/**
|
|
@@ -84,7 +76,7 @@ export interface ListResult<T = any> {
|
|
|
84
76
|
/**
|
|
85
77
|
* 事务回调函数
|
|
86
78
|
*/
|
|
87
|
-
export type TransactionCallback<T = any> = (trans:
|
|
79
|
+
export type TransactionCallback<T = any> = (trans: DbHelper) => Promise<T>;
|
|
88
80
|
|
|
89
81
|
/**
|
|
90
82
|
* SQL 查询结果
|
|
@@ -154,10 +146,11 @@ export interface SyncStats {
|
|
|
154
146
|
}
|
|
155
147
|
|
|
156
148
|
/**
|
|
157
|
-
*
|
|
149
|
+
* DbHelper 接口(前向声明)
|
|
158
150
|
*/
|
|
159
|
-
export interface
|
|
160
|
-
|
|
151
|
+
export interface DbHelper {
|
|
152
|
+
getCount(options: Omit<QueryOptions, 'fields' | 'page' | 'limit' | 'orderBy'>): Promise<number>;
|
|
153
|
+
getOne<T = any>(options: QueryOptions): Promise<T | null>;
|
|
161
154
|
getList<T = any>(options: QueryOptions): Promise<ListResult<T>>;
|
|
162
155
|
getAll<T = any>(options: Omit<QueryOptions, 'page' | 'limit'>): Promise<T[]>;
|
|
163
156
|
insData(options: InsertOptions): Promise<number>;
|
|
@@ -175,6 +168,8 @@ export interface SqlClientOptions {
|
|
|
175
168
|
max?: number;
|
|
176
169
|
/** 是否使用 BigInt */
|
|
177
170
|
bigint?: boolean;
|
|
171
|
+
/** 连接超时时间(毫秒),默认 5000ms */
|
|
172
|
+
connectionTimeout?: number;
|
|
178
173
|
/** 其他自定义选项 */
|
|
179
174
|
[key: string]: any;
|
|
180
175
|
}
|