midway-fatcms 0.0.1-beta.56 → 0.0.1-beta.58
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/dist/libs/crud-pro/utils/sqlConvert/convertColumnName.d.ts +1 -1
- package/dist/libs/crud-pro/utils/sqlConvert/convertMix.d.ts +1 -1
- package/dist/libs/crud-pro/utils/sqlConvert/convertMsSql.d.ts +1 -1
- package/dist/libs/crud-pro/utils/sqlConvert/convertPgSql.d.ts +1 -1
- package/dist/libs/utils/base64.d.ts +5 -5
- package/dist/libs/utils/base64.js +5 -5
- package/dist/libs/utils/render-utils.js +12 -14
- package/dist/schedule/runSchedule.js +1 -1
- package/dist/schedule/scheduleNames.js +2 -2
- package/dist/service/UserSessionService.js +1 -1
- package/dist/service/asyncTask/AsyncTaskRunnerService.js +3 -3
- package/dist/service/crudstd/CrudStdService.d.ts +1 -0
- package/dist/service/crudstd/CrudStdService.js +45 -2
- package/dist/service/curd/CurdProService.js +2 -2
- package/package.json +1 -1
- package/src/controller/gateway/AnyApiGatewayController.ts +33 -1
- package/src/controller/gateway/PublicApiController.ts +1 -1
- package/src/controller/gateway/StaticController.ts +2 -2
- package/src/libs/crud-pro/models/Transaction.ts +3 -5
- package/src/libs/crud-pro/services/CrudProServiceBase.ts +0 -1
- package/src/libs/crud-pro/utils/sqlConvert/convertColumnName.ts +3 -8
- package/src/libs/crud-pro/utils/sqlConvert/convertMix.ts +17 -19
- package/src/libs/crud-pro/utils/sqlConvert/convertMsSql.ts +4 -6
- package/src/libs/crud-pro/utils/sqlConvert/convertPgSql.ts +4 -6
- package/src/libs/crud-pro/utils/sqlConvert/convertPgType.ts +1 -3
- package/src/libs/global-config/global-config.ts +5 -6
- package/src/libs/utils/base64.ts +32 -39
- package/src/libs/utils/render-utils.ts +25 -34
- package/src/models/SystemEntities.ts +1 -3
- package/src/models/SystemPerm.ts +10 -11
- package/src/models/SystemTables.ts +0 -1
- package/src/models/bizmodels.ts +2 -4
- package/src/schedule/index.ts +4 -11
- package/src/schedule/runSchedule.ts +4 -12
- package/src/schedule/scheduleNames.ts +5 -11
- package/src/service/AuthService.ts +2 -3
- package/src/service/UserSessionService.ts +20 -24
- package/src/service/asyncTask/AsyncTaskRunnerService.ts +3 -9
- package/src/service/asyncTask/handler/ExportExcelByStdCrudHandler.ts +0 -1
- package/src/service/base/BaseService.ts +4 -9
- package/src/service/base/RedisCacheService.ts +7 -10
- package/src/service/crudstd/CrudStdService.ts +65 -11
- package/src/service/curd/CrudProQuick.ts +12 -14
- package/src/service/curd/CurdMixUtils.ts +0 -2
- package/src/service/curd/CurdProService.ts +2 -2
- package/src/service/proxyapi/ProxyApiLoadService.ts +1 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SqlCfgModel } from
|
|
1
|
+
import { SqlCfgModel } from '../../models/SqlCfgModel';
|
|
2
2
|
declare function toSqlColumnName(columnName: string, sqlCfgModel: SqlCfgModel): string;
|
|
3
3
|
declare function toSqlColumnNamesJoin(columns: string[], sqlCfgModel: SqlCfgModel): string;
|
|
4
4
|
export { toSqlColumnName, toSqlColumnNamesJoin };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
declare function replaceQuestionMarksForMssql(sql: string): string;
|
|
2
|
-
export { replaceQuestionMarksForMssql
|
|
2
|
+
export { replaceQuestionMarksForMssql };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
declare function replaceQuestionMarks(sql: string): string;
|
|
2
|
-
export { replaceQuestionMarks
|
|
2
|
+
export { replaceQuestionMarks };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
declare function toBase64(obj: any): string;
|
|
2
2
|
/**
|
|
3
|
-
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
4
|
-
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
5
|
-
* @returns 还原后的 JS 对象
|
|
6
|
-
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
7
|
-
*/
|
|
3
|
+
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
4
|
+
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
5
|
+
* @returns 还原后的 JS 对象
|
|
6
|
+
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
7
|
+
*/
|
|
8
8
|
declare function fromBase64(base64Str: string): any;
|
|
9
9
|
export { toBase64, fromBase64 };
|
|
@@ -7,11 +7,11 @@ function toBase64(obj) {
|
|
|
7
7
|
}
|
|
8
8
|
exports.toBase64 = toBase64;
|
|
9
9
|
/**
|
|
10
|
-
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
11
|
-
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
12
|
-
* @returns 还原后的 JS 对象
|
|
13
|
-
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
14
|
-
*/
|
|
10
|
+
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
11
|
+
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
12
|
+
* @returns 还原后的 JS 对象
|
|
13
|
+
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
14
|
+
*/
|
|
15
15
|
function fromBase64(base64Str) {
|
|
16
16
|
// 校验输入是否为字符串
|
|
17
17
|
if (typeof base64Str !== 'string') {
|
|
@@ -48,17 +48,19 @@ class RenderUtils {
|
|
|
48
48
|
const packageAssets = (0, functions_1.parseJsonObject)(props.package_assets) || {};
|
|
49
49
|
const fileList = _.get(packageAssets, 'data.fileList');
|
|
50
50
|
if (Array.isArray(fileList)) {
|
|
51
|
-
this.fileList = fileList.filter(
|
|
51
|
+
this.fileList = fileList.filter(f => {
|
|
52
52
|
return f && f.fileUrl && typeof f.fileUrl === 'string' && f.fileUrl.length > 5; // 至少五个字符。
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
56
|
this.fileList = [];
|
|
57
57
|
const time = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
|
|
58
|
-
console.info(time +
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
console.info(time +
|
|
59
|
+
' 解析fileList为空==>' +
|
|
60
|
+
JSON.stringify({
|
|
61
|
+
workbench_code: (_a = this.workbenchInfo) === null || _a === void 0 ? void 0 : _a.workbench_code,
|
|
62
|
+
app_code: (_b = this.appInfo) === null || _b === void 0 ? void 0 : _b.app_code,
|
|
63
|
+
}));
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
renderCsrfToken() {
|
|
@@ -68,15 +70,11 @@ class RenderUtils {
|
|
|
68
70
|
return `<script>window.__user_info = ${JSON.stringify(this.userInfo)} </script>`;
|
|
69
71
|
}
|
|
70
72
|
renderWorkbenchInfo() {
|
|
71
|
-
const infoPick = _.pick(this.workbenchInfo, [
|
|
72
|
-
'id', 'workbench_code', 'workbench_name', 'workbench_domain', 'workbench_desc', 'config_type', 'config_content'
|
|
73
|
-
]);
|
|
73
|
+
const infoPick = _.pick(this.workbenchInfo, ['id', 'workbench_code', 'workbench_name', 'workbench_domain', 'workbench_desc', 'config_type', 'config_content']);
|
|
74
74
|
return `<script>window.__workbench_info = ${JSON.stringify(infoPick)}</script>`;
|
|
75
75
|
}
|
|
76
76
|
renderAppInfo() {
|
|
77
|
-
const infoPick = _.pick(this.appInfo, [
|
|
78
|
-
'id', 'app_code', 'app_name', 'app_type', 'app_desc', 'config_type', 'config_content'
|
|
79
|
-
]);
|
|
77
|
+
const infoPick = _.pick(this.appInfo, ['id', 'app_code', 'app_name', 'app_type', 'app_desc', 'config_type', 'config_content']);
|
|
80
78
|
return `<script>window.__app_info = ${JSON.stringify(infoPick)}</script>`;
|
|
81
79
|
}
|
|
82
80
|
renderCookieInfo(keys) {
|
|
@@ -98,7 +96,7 @@ class RenderUtils {
|
|
|
98
96
|
}
|
|
99
97
|
}
|
|
100
98
|
renderJsAssets() {
|
|
101
|
-
const fileList = this.fileList.filter(
|
|
99
|
+
const fileList = this.fileList.filter(s => {
|
|
102
100
|
return s.fileType === 'js' || s.fileUrl.endsWith('.js');
|
|
103
101
|
});
|
|
104
102
|
const arr = fileList.map(f => {
|
|
@@ -110,13 +108,13 @@ class RenderUtils {
|
|
|
110
108
|
return arr.join('\n');
|
|
111
109
|
}
|
|
112
110
|
renderCssAssets() {
|
|
113
|
-
const fileList = this.fileList.filter(
|
|
111
|
+
const fileList = this.fileList.filter(s => {
|
|
114
112
|
return s.fileType === 'css' || s.fileUrl.endsWith('.css');
|
|
115
113
|
});
|
|
116
114
|
const fileUrlList = fileList.map(f => {
|
|
117
115
|
return f.fileUrl;
|
|
118
116
|
});
|
|
119
|
-
const arr = fileUrlList.map(
|
|
117
|
+
const arr = fileUrlList.map(url => {
|
|
120
118
|
return `<link href="${url}" rel="stylesheet" />`;
|
|
121
119
|
});
|
|
122
120
|
return arr.join('\n');
|
|
@@ -34,7 +34,7 @@ class ScheduleQueue {
|
|
|
34
34
|
const intervalTime1 = this.scheduleIntervalMap.get(serviceName);
|
|
35
35
|
const intervalTime = intervalTime1 || DEFAULT_SCHEDULE_INTERVAL; // 时间间隔
|
|
36
36
|
const lastExecuteTime = lastExecuteTimeMap[serviceName];
|
|
37
|
-
return
|
|
37
|
+
return Date.now() - lastExecuteTime >= intervalTime;
|
|
38
38
|
}
|
|
39
39
|
async runScheduleTaskOnceCheckTime(serviceName) {
|
|
40
40
|
// 还没有到可以执行时间
|
|
@@ -11,7 +11,7 @@ exports.INNER_SCHEDULE_INTERVAL = INNER_SCHEDULE_INTERVAL;
|
|
|
11
11
|
const INNER_SCHEDULE_NAMES = {
|
|
12
12
|
proxyApiLoadService: 'proxyApiLoadService',
|
|
13
13
|
workbenchService: 'workbenchService',
|
|
14
|
-
visitStatService:
|
|
15
|
-
asyncTaskRunnerService:
|
|
14
|
+
visitStatService: 'visitStatService',
|
|
15
|
+
asyncTaskRunnerService: 'asyncTaskRunnerService',
|
|
16
16
|
};
|
|
17
17
|
exports.INNER_SCHEDULE_NAMES = INNER_SCHEDULE_NAMES;
|
|
@@ -101,7 +101,7 @@ let UserSessionService = class UserSessionService {
|
|
|
101
101
|
columns: ['id', 'created_user_session'],
|
|
102
102
|
condition: {
|
|
103
103
|
id: asyncTaskId,
|
|
104
|
-
}
|
|
104
|
+
},
|
|
105
105
|
}, {
|
|
106
106
|
sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE,
|
|
107
107
|
sqlTable: SystemTables_1.SystemTables.sys_async_tasks,
|
|
@@ -154,18 +154,18 @@ let AsyncTaskRunnerService = class AsyncTaskRunnerService extends BaseService_1.
|
|
|
154
154
|
if (lock !== 'OK') {
|
|
155
155
|
return Promise.resolve();
|
|
156
156
|
}
|
|
157
|
-
const timeoutTime = moment().subtract(24, 'hours').format(
|
|
157
|
+
const timeoutTime = moment().subtract(24, 'hours').format('YYYY-MM-DD HH:mm:ss.SSS');
|
|
158
158
|
await this.curdProService.executeCrudByCfg({
|
|
159
159
|
condition: {
|
|
160
160
|
task_status: AsyncTaskModel_1.SysAsyncTaskStatus.RUNNING,
|
|
161
161
|
updated_at: {
|
|
162
162
|
$lt: timeoutTime,
|
|
163
|
-
}
|
|
163
|
+
},
|
|
164
164
|
},
|
|
165
165
|
data: {
|
|
166
166
|
task_status: AsyncTaskModel_1.SysAsyncTaskStatus.FAILED,
|
|
167
167
|
error_message: '任务超时',
|
|
168
|
-
}
|
|
168
|
+
},
|
|
169
169
|
}, {
|
|
170
170
|
sqlTable: SystemTables_1.SystemTables.sys_async_tasks,
|
|
171
171
|
sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE,
|
|
@@ -62,6 +62,7 @@ export declare class CrudStdService extends ApiBaseService {
|
|
|
62
62
|
*/
|
|
63
63
|
private getParsedCrudStdAppInfoPrivate;
|
|
64
64
|
private hasOperationPerm;
|
|
65
|
+
private fixCfgModelAndParamBySoftDelete;
|
|
65
66
|
private fixCfgModelByFilterValue;
|
|
66
67
|
private fixSubmitDataByKeepSubmitData;
|
|
67
68
|
private fixDataFieldTypeBySqlTableField;
|
|
@@ -29,17 +29,27 @@ exports.SPECIAL_SETTING_KEY = {
|
|
|
29
29
|
QUERY_LIST: 'QUERY_LIST',
|
|
30
30
|
QUERY_ONE: 'QUERY_ONE',
|
|
31
31
|
};
|
|
32
|
+
function isNotEmptyStr(str) {
|
|
33
|
+
return typeof str === 'string' && str.trim().length > 0;
|
|
34
|
+
}
|
|
32
35
|
function getExecuteTableNameBySettingKey(appInfo, stdAction) {
|
|
33
36
|
const { settingKey } = stdAction || {};
|
|
34
37
|
const stdCrudCfgObj = appInfo.stdCrudCfgObj;
|
|
35
38
|
const actionsMap = appInfo.actionsMap || {};
|
|
39
|
+
// 操作按钮单独设置了mainTableName字段
|
|
36
40
|
const actionCfg = actionsMap[settingKey];
|
|
37
41
|
if (actionCfg) {
|
|
38
42
|
const mainTableName = _.get(actionCfg, 'component.props.mainTableName');
|
|
39
|
-
if (
|
|
43
|
+
if (isNotEmptyStr(mainTableName)) {
|
|
40
44
|
return mainTableName.trim();
|
|
41
45
|
}
|
|
42
46
|
}
|
|
47
|
+
// 全局配置了mainTableName字段
|
|
48
|
+
const globalMainTableName = _.get(stdCrudCfgObj, 'othersSetting.values.globalMainTableName');
|
|
49
|
+
if (isNotEmptyStr(globalMainTableName)) {
|
|
50
|
+
return globalMainTableName.trim();
|
|
51
|
+
}
|
|
52
|
+
// 视图中配置的表。
|
|
43
53
|
return stdCrudCfgObj.tableBaseInfo.tableName;
|
|
44
54
|
}
|
|
45
55
|
let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseService {
|
|
@@ -70,6 +80,8 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
70
80
|
if (!appInfo.settingKeyActionCfg.hasOperationPerm) {
|
|
71
81
|
throw new devops_1.BizException('没有权限');
|
|
72
82
|
}
|
|
83
|
+
// 软删除操作。
|
|
84
|
+
await this.fixCfgModelAndParamBySoftDelete(params, cfgModel, appInfo, sqlSimpleName);
|
|
73
85
|
// 根据用户配置,设置关联查询的数据信息。
|
|
74
86
|
await this.crudStdRelationService.addCfgModelColumnsRelation(cfgModel, appInfo);
|
|
75
87
|
// 根据FilterValue参数,设置updateCfg
|
|
@@ -208,7 +220,7 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
208
220
|
* @private
|
|
209
221
|
*/
|
|
210
222
|
async getParsedCrudStdAppInfo(appCode) {
|
|
211
|
-
const cacheKey =
|
|
223
|
+
const cacheKey = 'getParsedCrudStdAppInfo:' + appCode;
|
|
212
224
|
let appInfo = this.getFromCtxCache(cacheKey);
|
|
213
225
|
if (!appInfo) {
|
|
214
226
|
appInfo = await this.getParsedCrudStdAppInfoPrivate(appCode);
|
|
@@ -259,6 +271,37 @@ let CrudStdService = class CrudStdService extends ApiBaseService_1.ApiBaseServic
|
|
|
259
271
|
}
|
|
260
272
|
return true; // 无需鉴权
|
|
261
273
|
}
|
|
274
|
+
async fixCfgModelAndParamBySoftDelete(params, cfgModel, appInfo, sqlSimpleName) {
|
|
275
|
+
var _a, _b;
|
|
276
|
+
const stdCrudCfgObj = appInfo.stdCrudCfgObj;
|
|
277
|
+
//删除策略
|
|
278
|
+
const deleteStrategy = _.get(stdCrudCfgObj, 'othersSetting.values.deleteStrategy');
|
|
279
|
+
if (deleteStrategy !== 'soft') {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// 删除操作,如果是软删除修改为update语句。
|
|
283
|
+
// 标准软删除:deleted_at 字段为0代表未删除,有任意时间字段代表已删除。
|
|
284
|
+
if (keys_1.KeysOfSimpleSQL.SIMPLE_DELETE === sqlSimpleName) {
|
|
285
|
+
const userSession = (_b = (_a = this.ctx) === null || _a === void 0 ? void 0 : _a.userSession) === null || _b === void 0 ? void 0 : _b.getSessionInfo();
|
|
286
|
+
if (!params.data) {
|
|
287
|
+
params.data = {};
|
|
288
|
+
}
|
|
289
|
+
params.data.deleted_at = Date.now(); // 默认值为 0; 0代表未删除
|
|
290
|
+
params.data.deleted_by = (userSession === null || userSession === void 0 ? void 0 : userSession.accountId) || "";
|
|
291
|
+
// 执行update操作
|
|
292
|
+
cfgModel.sqlSimpleName = keys_1.KeysOfSimpleSQL.SIMPLE_UPDATE;
|
|
293
|
+
if (!params.condition || Object.keys(params.condition).length === 0) {
|
|
294
|
+
throw new Error('执行删除操作,必须指定删除条件');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// 查询操作。强制查询未删除的。
|
|
298
|
+
if (keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE === sqlSimpleName || keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE === sqlSimpleName) {
|
|
299
|
+
if (!params.condition) {
|
|
300
|
+
params.condition = {};
|
|
301
|
+
}
|
|
302
|
+
params.condition.deleted_at = 0; // 未删除
|
|
303
|
+
}
|
|
304
|
+
}
|
|
262
305
|
async fixCfgModelByFilterValue(params, cfgModel, appInfo, arg3) {
|
|
263
306
|
const { filterValue } = params || {};
|
|
264
307
|
if (!filterValue && filterValue !== 0) {
|
|
@@ -37,7 +37,7 @@ function toVisitor(ctx) {
|
|
|
37
37
|
roleCodes: [],
|
|
38
38
|
functionCodes: [],
|
|
39
39
|
workbenchCode: (workbenchInfo === null || workbenchInfo === void 0 ? void 0 : workbenchInfo.workbench_code) || '',
|
|
40
|
-
bizExt: {}
|
|
40
|
+
bizExt: {},
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
const sessionInfo = userSession.getSessionInfo();
|
|
@@ -51,7 +51,7 @@ function toVisitor(ctx) {
|
|
|
51
51
|
roleCodes: sessionInfo.roleCodes || [],
|
|
52
52
|
functionCodes: sessionInfo.functionCodes || [],
|
|
53
53
|
workbenchCode: (workbenchInfo === null || workbenchInfo === void 0 ? void 0 : workbenchInfo.workbench_code) || '',
|
|
54
|
-
bizExt: sessionInfo.bizExt || {}
|
|
54
|
+
bizExt: sessionInfo.bizExt || {},
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
class MyContextFunc extends ExecuteContextFunc_1.BaseExecuteContextFunc {
|
package/package.json
CHANGED
|
@@ -1 +1,33 @@
|
|
|
1
|
-
import { All, Controller, Inject, Param } from '@midwayjs/core';
|
|
2
1
|
* FaaS方式配置的接口
|
|
3
2
|
*/
|
|
4
3
|
@Inject()
|
|
5
4
|
protected ctx: Context;
|
|
6
5
|
@Inject()
|
|
7
6
|
private anyApiService: AnyApiService;
|
|
8
7
|
/**
|
|
9
8
|
* 执行配置出来的接口的接口。此接口本身不需要鉴权。鉴权信息在配置中由curdPro底层进行鉴权
|
|
10
9
|
*/
|
|
11
10
|
@All('/execute/:methodCode')
|
|
12
11
|
async executeAnyApiMethod(@Param('methodCode') methodCode: string) {
|
|
13
12
|
if (!methodCode) {
|
|
14
13
|
throw 'method参数不存在';
|
|
15
14
|
}
|
|
16
15
|
const headers = _.get(this.ctx, 'request.headers') || {};
|
|
17
16
|
const body = _.get(this.ctx, 'request.body') || {};
|
|
18
17
|
const query = this.ctx.query || {};
|
|
19
18
|
return await this.anyApiService.executeAnyApiMethod(methodCode, headers, body, query);
|
|
20
19
|
}
|
|
20
|
+
import { All, Controller, Inject, Param } from '@midwayjs/core';
|
|
21
|
+
import { Context } from '@midwayjs/koa';
|
|
22
|
+
import { BaseApiController } from '../base/BaseApiController';
|
|
23
|
+
import * as _ from 'lodash';
|
|
24
|
+
import { AnyApiService } from '@/service/anyapi/AnyApiService';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* FaaS方式配置的接口
|
|
28
|
+
*/
|
|
29
|
+
@Controller('/ns/gw/anyApi')
|
|
30
|
+
export class AnyApiGatewayController extends BaseApiController {
|
|
31
|
+
@Inject()
|
|
32
|
+
protected ctx: Context;
|
|
33
|
+
|
|
34
|
+
@Inject()
|
|
35
|
+
private anyApiService: AnyApiService;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 执行配置出来的接口的接口。此接口本身不需要鉴权。鉴权信息在配置中由curdPro底层进行鉴权
|
|
39
|
+
*/
|
|
40
|
+
@All('/execute/:methodCode')
|
|
41
|
+
async executeAnyApiMethod(@Param('methodCode') methodCode: string) {
|
|
42
|
+
if (!methodCode) {
|
|
43
|
+
throw 'method参数不存在';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const headers = _.get(this.ctx, 'request.headers') || {};
|
|
47
|
+
const body = _.get(this.ctx, 'request.body') || {};
|
|
48
|
+
const query = this.ctx.query || {};
|
|
49
|
+
|
|
50
|
+
return await this.anyApiService.executeAnyApiMethod(methodCode, headers, body, query);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -6,7 +6,7 @@ import * as fs2 from 'fs';
|
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import * as https from 'https';
|
|
8
8
|
import { parseJsonObject } from '@/libs/utils/functions';
|
|
9
|
-
import { ANONYMOUS_CONTEXT } from
|
|
9
|
+
import { ANONYMOUS_CONTEXT } from '@/schedule';
|
|
10
10
|
|
|
11
11
|
interface HttpGetRes {
|
|
12
12
|
statusCode: number;
|
|
@@ -131,7 +131,7 @@ export class StaticController extends BaseApiController {
|
|
|
131
131
|
|
|
132
132
|
@All('/:ossName/:relativePath+')
|
|
133
133
|
async proxyStaticFile(@Param('ossName') ossName: string, @Param('relativePath') relativePath: string) {
|
|
134
|
-
await this.initNotFoundList()
|
|
134
|
+
await this.initNotFoundList();
|
|
135
135
|
const { localDir } = this.getLocalPaths();
|
|
136
136
|
const PATH_CONFIG = getPathConfig(ossName);
|
|
137
137
|
|
|
@@ -8,8 +8,7 @@ class Transaction {
|
|
|
8
8
|
private transactionMySQL: TransactionMySQL = new TransactionMySQL();
|
|
9
9
|
private transactionPostgres: TransactionPostgres = new TransactionPostgres();
|
|
10
10
|
private transactionSqlServer: TransactionSqlServer = new TransactionSqlServer();
|
|
11
|
-
private isReleased
|
|
12
|
-
|
|
11
|
+
private isReleased = false;
|
|
13
12
|
|
|
14
13
|
private getTxObj(pool: IConnectionPool): TransactionMySQL | TransactionPostgres | TransactionSqlServer {
|
|
15
14
|
if (pool.dbType === SqlDbType.postgres) {
|
|
@@ -31,11 +30,10 @@ class Transaction {
|
|
|
31
30
|
* @param pool
|
|
32
31
|
*/
|
|
33
32
|
public async getTxConnection(pool: IConnectionPool): Promise<IPoolConnectionClient> {
|
|
34
|
-
|
|
35
|
-
if(this.isReleased) {
|
|
33
|
+
if (this.isReleased) {
|
|
36
34
|
const msg = '[Transaction] getTxConnection error, the txObject is isReleased, please check your code . DB request must be await';
|
|
37
35
|
console.error(msg);
|
|
38
|
-
throw new Error(msg)
|
|
36
|
+
throw new Error(msg);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
const txObj = this.getTxObj(pool);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {SqlCfgModel} from
|
|
2
|
-
import {SqlDbType} from
|
|
3
|
-
|
|
1
|
+
import { SqlCfgModel } from '../../models/SqlCfgModel';
|
|
2
|
+
import { SqlDbType } from '../../models/keys';
|
|
4
3
|
|
|
5
4
|
function toSqlColumnName(columnName: string, sqlCfgModel: SqlCfgModel): string {
|
|
6
5
|
if (sqlCfgModel.sqlDbType === SqlDbType.postgres) {
|
|
@@ -19,8 +18,4 @@ function toSqlColumnNamesJoin(columns: string[], sqlCfgModel: SqlCfgModel): stri
|
|
|
19
18
|
return columns2.join(',');
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
export {
|
|
24
|
-
toSqlColumnName,
|
|
25
|
-
toSqlColumnNamesJoin
|
|
26
|
-
}
|
|
21
|
+
export { toSqlColumnName, toSqlColumnNamesJoin };
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import { SqlDbType } from
|
|
2
|
-
import { pickAndConvertPgRows } from
|
|
3
|
-
import * as _ from 'lodash'
|
|
1
|
+
import { SqlDbType } from '../../models/keys';
|
|
2
|
+
import { pickAndConvertPgRows } from './convertPgType';
|
|
3
|
+
import * as _ from 'lodash';
|
|
4
4
|
|
|
5
5
|
function pickAndConvertRowsByMix(connectionQueryRes: any, sqlDbType: SqlDbType): any[] | any {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
if (!connectionQueryRes) {
|
|
7
|
+
throw new Error('[pickAndConvertRowsByMix] error, connectionQueryRes is null ');
|
|
8
|
+
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
if (sqlDbType === SqlDbType.postgres) {
|
|
11
|
+
return pickAndConvertPgRows(connectionQueryRes);
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if (sqlDbType === SqlDbType.mysql) {
|
|
15
|
+
return connectionQueryRes[0];
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
if (sqlDbType === SqlDbType.sqlserver) {
|
|
19
|
+
return _.get(connectionQueryRes, 'recordsets[0]') || [];
|
|
20
|
+
}
|
|
21
|
+
throw new Error('[pickAndConvertRowsByMix] error sqlDbType, sqlDbType = ' + sqlDbType);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export {
|
|
25
|
-
pickAndConvertRowsByMix
|
|
26
|
-
}
|
|
24
|
+
export { pickAndConvertRowsByMix };
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
function replaceQuestionMarksForMssql(sql:string): string {
|
|
1
|
+
function replaceQuestionMarksForMssql(sql: string): string {
|
|
2
2
|
let count = 0;
|
|
3
3
|
return sql.replace(/\?/g, () => {
|
|
4
|
-
count = count+ 1;
|
|
5
|
-
return `@fatcms_ms${count}
|
|
4
|
+
count = count + 1;
|
|
5
|
+
return `@fatcms_ms${count}`;
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export {
|
|
10
|
-
replaceQuestionMarksForMssql,
|
|
11
|
-
}
|
|
9
|
+
export { replaceQuestionMarksForMssql };
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
function replaceQuestionMarks(sql:string): string {
|
|
1
|
+
function replaceQuestionMarks(sql: string): string {
|
|
2
2
|
let count = 0;
|
|
3
3
|
return sql.replace(/\?/g, () => {
|
|
4
|
-
count = count+ 1;
|
|
5
|
-
return `$${count}
|
|
4
|
+
count = count + 1;
|
|
5
|
+
return `$${count}`;
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export {
|
|
10
|
-
replaceQuestionMarks,
|
|
11
|
-
}
|
|
9
|
+
export { replaceQuestionMarks };
|
|
@@ -31,14 +31,13 @@ interface IGlobalStaticConfig {
|
|
|
31
31
|
*/
|
|
32
32
|
bizUpdateCfgModelForCrudMtd(reqJson: any, cfgModel: any, methodInfo: any, ctx: any): Promise<any>;
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
/**
|
|
36
35
|
* CrudMtd: 业务系统自定义的修改ExecuteContext
|
|
37
|
-
* @param reqJson
|
|
38
|
-
* @param cfgModel
|
|
39
|
-
* @param methodInfo
|
|
40
|
-
* @param ctx
|
|
41
|
-
* @param executeContext
|
|
36
|
+
* @param reqJson
|
|
37
|
+
* @param cfgModel
|
|
38
|
+
* @param methodInfo
|
|
39
|
+
* @param ctx
|
|
40
|
+
* @param executeContext
|
|
42
41
|
*/
|
|
43
42
|
bizUpdateExecuteContextForCrudMtd(reqJson: any, cfgModel: any, methodInfo: any, ctx: any, executeContext: ExecuteContext): Promise<any>;
|
|
44
43
|
|
package/src/libs/utils/base64.ts
CHANGED
|
@@ -1,47 +1,40 @@
|
|
|
1
1
|
function toBase64(obj: any): string {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const jsonString = JSON.stringify(obj);
|
|
3
|
+
return Buffer.from(jsonString, 'utf8').toString('base64');
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
6
|
/**
|
|
9
|
-
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
10
|
-
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
11
|
-
* @returns 还原后的 JS 对象
|
|
12
|
-
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
13
|
-
*/
|
|
7
|
+
* 将经 toBase64 函数序列化的 Base64 字符串还原为 JS 对象
|
|
8
|
+
* @param base64Str - 经 toBase64 处理后的 Base64 字符串
|
|
9
|
+
* @returns 还原后的 JS 对象
|
|
10
|
+
* @throws 当 Base64 格式无效或 JSON 解析失败时抛出含具体原因的错误
|
|
11
|
+
*/
|
|
14
12
|
function fromBase64(base64Str: string): any {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
13
|
+
// 校验输入是否为字符串
|
|
14
|
+
if (typeof base64Str !== 'string') {
|
|
15
|
+
throw new Error('input must Base64 string');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// 1. 反向步骤1:将 Base64 字符串解码为 UTF-8 格式的 JSON 字符串
|
|
20
|
+
// 对应原函数的 Buffer.from(jsonString, 'utf8') 反向操作
|
|
21
|
+
const jsonString = Buffer.from(base64Str, 'base64').toString('utf8');
|
|
22
|
+
|
|
23
|
+
// 2. 反向步骤2:将 JSON 字符串解析为 JS 对象
|
|
24
|
+
// 对应原函数的 JSON.stringify(obj) 反向操作
|
|
25
|
+
const restoredObj = JSON.parse(jsonString);
|
|
26
|
+
|
|
27
|
+
return restoredObj;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// 分类处理不同错误类型,提供明确提示
|
|
30
|
+
if (error instanceof TypeError && error.message.includes('invalid base64')) {
|
|
31
|
+
throw new Error('还原失败:输入不是有效的 Base64 字符串');
|
|
32
|
+
} else if (error instanceof SyntaxError && error.message.includes('JSON')) {
|
|
33
|
+
throw new Error('还原失败:解码后的内容不是有效的 JSON 格式');
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error(`还原失败:未知错误 - ${(error as Error).message}`);
|
|
39
36
|
}
|
|
37
|
+
}
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
export {
|
|
45
|
-
toBase64,
|
|
46
|
-
fromBase64
|
|
47
|
-
}
|
|
40
|
+
export { toBase64, fromBase64 };
|