@steedos/objectql 2.2.51-beta.1 → 2.2.51-beta.2
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 +10 -10
- package/src/actions/field_updates.ts +0 -118
- package/src/actions/index.ts +0 -3
- package/src/actions/types/field_update_target.ts +0 -7
- package/src/actions/types/workflow_notification.ts +0 -9
- package/src/actions/types/workflow_rule.ts +0 -11
- package/src/actions/workflow_notifications.ts +0 -81
- package/src/actions/workflow_rule.ts +0 -136
- package/src/driver/driver.ts +0 -102
- package/src/driver/field-encrytion/index.ts +0 -8
- package/src/driver/field-encrytion/sharedconst.ts +0 -34
- package/src/driver/fieldDBType.ts +0 -14
- package/src/driver/format.ts +0 -36
- package/src/driver/index.ts +0 -20
- package/src/driver/metadata.ts +0 -226
- package/src/driver/meteorMongo.ts +0 -639
- package/src/driver/mongo.ts +0 -416
- package/src/driver/mysql.ts +0 -47
- package/src/driver/oracle.ts +0 -60
- package/src/driver/postgres.ts +0 -46
- package/src/driver/sqlite3.ts +0 -40
- package/src/driver/sqlserver.ts +0 -52
- package/src/dynamic-load/actions.ts +0 -146
- package/src/dynamic-load/approval_process.ts +0 -73
- package/src/dynamic-load/button.ts +0 -75
- package/src/dynamic-load/chart.ts +0 -22
- package/src/dynamic-load/client_script.ts +0 -65
- package/src/dynamic-load/field.ts +0 -77
- package/src/dynamic-load/flow_role.ts +0 -46
- package/src/dynamic-load/index.ts +0 -21
- package/src/dynamic-load/layout.ts +0 -53
- package/src/dynamic-load/listview.ts +0 -57
- package/src/dynamic-load/method.ts +0 -63
- package/src/dynamic-load/object_translations.ts +0 -61
- package/src/dynamic-load/originalObject.ts +0 -8
- package/src/dynamic-load/package.ts +0 -312
- package/src/dynamic-load/page.ts +0 -23
- package/src/dynamic-load/permission.ts +0 -71
- package/src/dynamic-load/permissionset.ts +0 -78
- package/src/dynamic-load/preload_data.ts +0 -104
- package/src/dynamic-load/profile.ts +0 -90
- package/src/dynamic-load/query.ts +0 -22
- package/src/dynamic-load/restrictionRules.ts +0 -23
- package/src/dynamic-load/role.ts +0 -46
- package/src/dynamic-load/shareRules.ts +0 -23
- package/src/dynamic-load/tab.ts +0 -17
- package/src/dynamic-load/tabs.ts +0 -13
- package/src/dynamic-load/translations.ts +0 -54
- package/src/dynamic-load/trigger.ts +0 -236
- package/src/dynamic-load/validation_rule.ts +0 -77
- package/src/dynamic-load/workflow.ts +0 -114
- package/src/errors/index.ts +0 -111
- package/src/formula/core.ts +0 -490
- package/src/formula/field_formula.ts +0 -107
- package/src/formula/index.ts +0 -81
- package/src/formula/params.ts +0 -197
- package/src/formula/recompute.ts +0 -65
- package/src/formula/simple_params.ts +0 -92
- package/src/formula/type.ts +0 -107
- package/src/formula/util.ts +0 -207
- package/src/index.ts +0 -24
- package/src/metadata-register/_base.ts +0 -85
- package/src/metadata-register/app.ts +0 -30
- package/src/metadata-register/chart.ts +0 -9
- package/src/metadata-register/index.ts +0 -123
- package/src/metadata-register/layout.ts +0 -38
- package/src/metadata-register/object.ts +0 -68
- package/src/metadata-register/page.ts +0 -9
- package/src/metadata-register/permissionFields.ts +0 -13
- package/src/metadata-register/permissionset.ts +0 -25
- package/src/metadata-register/process.ts +0 -16
- package/src/metadata-register/processTrigger.ts +0 -24
- package/src/metadata-register/profile.ts +0 -25
- package/src/metadata-register/query.ts +0 -9
- package/src/metadata-register/restrictionRules.ts +0 -12
- package/src/metadata-register/shareRules.ts +0 -13
- package/src/metadata-register/tab.ts +0 -9
- package/src/metadata-register/tabs.ts +0 -43
- package/src/services/datasourceServiceFactory.ts +0 -55
- package/src/services/helpers/graphql/consts.ts +0 -25
- package/src/services/helpers/graphql/getPrimaryFieldType.ts +0 -48
- package/src/services/helpers/graphql/getQueryFields.ts +0 -51
- package/src/services/helpers/graphql/index.ts +0 -666
- package/src/services/helpers/rest.ts +0 -57
- package/src/services/index.ts +0 -13
- package/src/services/objectService.ts +0 -846
- package/src/services/objectServiceDispatcher.ts +0 -209
- package/src/services/objectServiceFactory.ts +0 -29
- package/src/summary/core.ts +0 -263
- package/src/summary/field_summary.ts +0 -71
- package/src/summary/index.ts +0 -96
- package/src/summary/recompute.ts +0 -31
- package/src/summary/type.ts +0 -60
- package/src/ts-types/index.ts +0 -3
- package/src/ts-types/permissionset.ts +0 -8
- package/src/ts-types/profile.ts +0 -11
- package/src/ts-types/triggerActionParams.ts +0 -22
- package/src/typeorm/driver.ts +0 -379
- package/src/typeorm/index.ts +0 -3
- package/src/typeorm/util.ts +0 -147
- package/src/types/action.ts +0 -52
- package/src/types/app.ts +0 -280
- package/src/types/config.ts +0 -152
- package/src/types/connection.ts +0 -87
- package/src/types/dashboard.ts +0 -91
- package/src/types/datasource.ts +0 -570
- package/src/types/field.ts +0 -370
- package/src/types/field_permission.ts +0 -42
- package/src/types/field_types.ts +0 -1
- package/src/types/index.ts +0 -21
- package/src/types/list_view.ts +0 -56
- package/src/types/listeners.ts +0 -18
- package/src/types/object.ts +0 -2076
- package/src/types/object_dynamic_load.ts +0 -426
- package/src/types/object_events.ts +0 -43
- package/src/types/object_layouts.ts +0 -20
- package/src/types/object_permission.ts +0 -134
- package/src/types/query.ts +0 -28
- package/src/types/report.ts +0 -128
- package/src/types/restrictionRule.ts +0 -57
- package/src/types/schema.ts +0 -273
- package/src/types/shareRule.ts +0 -57
- package/src/types/trigger.ts +0 -88
- package/src/types/userSession.ts +0 -45
- package/src/types/validation_rules.ts +0 -29
- package/src/util/convert.ts +0 -131
- package/src/util/field.ts +0 -93
- package/src/util/function_expression.ts +0 -63
- package/src/util/index.ts +0 -1066
- package/src/util/locale.ts +0 -24
- package/src/util/permission_shares.ts +0 -25
- package/src/util/suffix.ts +0 -78
- package/src/util/transform.ts +0 -239
- package/src/validators/index.ts +0 -36
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/objectql",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.2.51-beta.
|
|
4
|
+
"version": "2.2.51-beta.2",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"@babel/preset-env": "^7.8.4",
|
|
19
19
|
"@salesforce/kit": "^1.0.4",
|
|
20
20
|
"@salesforce/ts-types": "^1.1.1",
|
|
21
|
-
"@steedos/cachers": "2.2.51-beta.
|
|
22
|
-
"@steedos/filters": "2.2.51-beta.
|
|
23
|
-
"@steedos/formula": "2.2.51-beta.
|
|
24
|
-
"@steedos/metadata-core": "2.2.51-beta.
|
|
25
|
-
"@steedos/odata-v4-typeorm": "2.2.51-beta.
|
|
26
|
-
"@steedos/schemas": "2.2.51-beta.
|
|
27
|
-
"@steedos/standard-objects": "2.2.51-beta.
|
|
21
|
+
"@steedos/cachers": "2.2.51-beta.2",
|
|
22
|
+
"@steedos/filters": "2.2.51-beta.2",
|
|
23
|
+
"@steedos/formula": "2.2.51-beta.2",
|
|
24
|
+
"@steedos/metadata-core": "2.2.51-beta.2",
|
|
25
|
+
"@steedos/odata-v4-typeorm": "2.2.51-beta.2",
|
|
26
|
+
"@steedos/schemas": "2.2.51-beta.2",
|
|
27
|
+
"@steedos/standard-objects": "2.2.51-beta.2",
|
|
28
28
|
"app-root-path": "^2.2.1",
|
|
29
29
|
"body-parser": "^1.18.1",
|
|
30
30
|
"bunyan-sfdx-no-dtrace": "^1.8.2",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@salesforce/dev-config": "^1.4.4",
|
|
55
55
|
"@salesforce/dev-scripts": "0.3.12",
|
|
56
|
-
"@steedos/meteor-bundle-runner": "2.2.51-beta.
|
|
56
|
+
"@steedos/meteor-bundle-runner": "2.2.51-beta.2",
|
|
57
57
|
"@types/chai": "^4.1.7",
|
|
58
58
|
"@types/chai-as-promised": "7.1.0",
|
|
59
59
|
"@types/express": "^4.16.1",
|
|
@@ -76,5 +76,5 @@
|
|
|
76
76
|
"publishConfig": {
|
|
77
77
|
"access": "public"
|
|
78
78
|
},
|
|
79
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "c324c40fa8facd3bf73a51e8c417293a9349f9fb"
|
|
80
80
|
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { getObject, computeFormula, SteedosError } from '../index';
|
|
2
|
-
import { runQuotedByObjectFieldFormulas } from '../formula';
|
|
3
|
-
import { runQuotedByObjectFieldSummaries } from '../summary';
|
|
4
|
-
import { FieldUpdateTarget } from './types/field_update_target';
|
|
5
|
-
const _ = require('underscore');
|
|
6
|
-
|
|
7
|
-
const getFieldValue = async (action: any, recordId: string, userSession: any)=>{
|
|
8
|
-
switch (action.operation) {
|
|
9
|
-
case 'null':
|
|
10
|
-
return null;
|
|
11
|
-
case 'literal':
|
|
12
|
-
return action.literal_value
|
|
13
|
-
case 'formula':
|
|
14
|
-
return await computeFormula(action.formula, action.object_name, recordId, userSession.userId, userSession.spaceId);
|
|
15
|
-
default:
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function getFieldUpdateActionTargetObjectName(action: any){
|
|
21
|
-
const isCrossedObject = action.target_object != action.object_name;
|
|
22
|
-
if(isCrossedObject){
|
|
23
|
-
// 如果是跨对象字段更新,则target_object保存的是关联字段名,而不是对象名称
|
|
24
|
-
let result = getObject(action.object_name).getField(action.target_object).reference_to;
|
|
25
|
-
if(!_.isString(result)){
|
|
26
|
-
throw new SteedosError('target_object must be a string');
|
|
27
|
-
}
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
else{
|
|
31
|
-
return action.object_name;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function runFieldUpdateAction(action: any, recordId: any, userSession: any){
|
|
36
|
-
const record = await getObject(action.object_name).findOne(recordId, null);
|
|
37
|
-
let recordIdToUpdate: string;
|
|
38
|
-
let previousRecord: any;
|
|
39
|
-
let needToReevaluate = false;//是否返回FieldUpdateTarget以备字段更改后重新评估工作流规则。
|
|
40
|
-
// 需要注意的是needToReevaluate与字段更新上的reevaluate_on_change这个勾选框属性有关,
|
|
41
|
-
// 但是reevaluate_on_change这个勾选框只标识是否重新评估字段更新所关联的对象的工作流规则,
|
|
42
|
-
// 对于跨对象的字段更新,始终不会重新评估这些工作流规则,且始终会重新评估其要更新的对象的所有工作流规则。
|
|
43
|
-
const isCrossedObject = action.target_object != action.object_name; //因不允许字段名(api_name)配置成所属对象api_name同名值,所以这里直接这样判断就行了
|
|
44
|
-
const mainObjectName = getFieldUpdateActionTargetObjectName(action);
|
|
45
|
-
if(isCrossedObject){
|
|
46
|
-
// 跨对象字段更新
|
|
47
|
-
recordIdToUpdate = record[action.target_object];
|
|
48
|
-
previousRecord = recordIdToUpdate && await getObject(mainObjectName).findOne(recordIdToUpdate, null);
|
|
49
|
-
//对于跨对象的字段更新,虽然始终不会重新评估字段更新关联对象的工作流规则,但是始终会重新评估其要更新的对象的所有工作流规则。
|
|
50
|
-
needToReevaluate = true;
|
|
51
|
-
}else{
|
|
52
|
-
// 本对象字段更新
|
|
53
|
-
recordIdToUpdate = record._id;
|
|
54
|
-
previousRecord = record;
|
|
55
|
-
//对于非跨对象的字段更新,是否重新评估字段更新关联对象的工作流规则由其属性reevaluate_on_change决定。
|
|
56
|
-
needToReevaluate = action.reevaluate_on_change;
|
|
57
|
-
}
|
|
58
|
-
const objectToUpdate = getObject(mainObjectName);
|
|
59
|
-
const fieldToUpdate = objectToUpdate.getField(action.field_name);
|
|
60
|
-
if(["formula", "summary", "autonumber"].indexOf(fieldToUpdate.type) > -1){
|
|
61
|
-
// 公式、累计汇总、自动编号三种字段类型是只读的,不允许字段更新来变更其值
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
const newFieldValue = await getFieldValue(action, recordId, userSession);
|
|
65
|
-
if(recordIdToUpdate && newFieldValue !== (previousRecord && previousRecord[action.field_name])){
|
|
66
|
-
if(action.undirect === true){
|
|
67
|
-
await objectToUpdate.update(recordIdToUpdate, {[action.field_name]: newFieldValue});
|
|
68
|
-
}else{
|
|
69
|
-
// 只有值变更时才执行字段更新、级联公式重算、级联汇总字段重算、重新评估工作流规则等操作
|
|
70
|
-
await objectToUpdate.directUpdate(recordIdToUpdate, {[action.field_name]: newFieldValue});
|
|
71
|
-
// 字段更新后,需要找到引用了该字段的公式字段并更新其值
|
|
72
|
-
await runQuotedByObjectFieldFormulas(mainObjectName, recordIdToUpdate, userSession, {
|
|
73
|
-
fieldNames: [action.field_name]
|
|
74
|
-
});
|
|
75
|
-
// 字段更新后,需要找到引用了该字段的累计汇总字段并更新其值
|
|
76
|
-
await runQuotedByObjectFieldSummaries(mainObjectName, recordIdToUpdate, null, userSession, {
|
|
77
|
-
fieldNames: [action.field_name]
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
else{
|
|
82
|
-
// 值没变更时强制重置needToReevaluate为false,即不需要执行相关工作流规则重新评估
|
|
83
|
-
needToReevaluate = false;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if(needToReevaluate){
|
|
87
|
-
return <FieldUpdateTarget>{
|
|
88
|
-
object_name: mainObjectName,
|
|
89
|
-
record_id: recordIdToUpdate,
|
|
90
|
-
field_name: action.field_name,
|
|
91
|
-
previous_record: previousRecord
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
else{
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export async function runFieldUpdateActions(ids: Array<string>, recordId: any, userSession: any){
|
|
100
|
-
|
|
101
|
-
const filters = [];
|
|
102
|
-
let targets: Array<FieldUpdateTarget> = [];
|
|
103
|
-
|
|
104
|
-
if(!_.isEmpty(ids)){
|
|
105
|
-
filters.push([['name', 'in', ids],'or', ['_id', 'in', ids]])
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if(!_.isEmpty(filters)){
|
|
109
|
-
const actions = await getObject("action_field_updates").find({filters: filters})
|
|
110
|
-
for (const action of actions) {
|
|
111
|
-
const target:FieldUpdateTarget = await runFieldUpdateAction(action, recordId, userSession);
|
|
112
|
-
if(target){
|
|
113
|
-
targets.push(target);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return targets;
|
|
118
|
-
}
|
package/src/actions/index.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { getObject, computeFormula } from '../index';
|
|
2
|
-
|
|
3
|
-
import { WorkflowNotification } from './types/workflow_notification';
|
|
4
|
-
|
|
5
|
-
import _ = require('underscore');
|
|
6
|
-
|
|
7
|
-
declare var Creator: any;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* @param ids workflow_notifications'id
|
|
12
|
-
* @param recordId object record id
|
|
13
|
-
* @param userSession
|
|
14
|
-
*/
|
|
15
|
-
export async function runWorkflowNotifyActions(ids: Array<string>, recordId: any, userSession: any) {
|
|
16
|
-
if (_.isEmpty(ids) || _.isEmpty(recordId) || _.isEmpty(userSession)) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
let filters = [['name', 'in', ids],'or', ['_id', 'in', ids]];
|
|
20
|
-
let notifications = await getObject("workflow_notifications").find({ filters: filters })
|
|
21
|
-
for (const wn of notifications) {
|
|
22
|
-
await runWorkflowNotifyAction(wn, recordId, userSession);
|
|
23
|
-
}
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
* @param workflowNotification
|
|
30
|
-
* @param recordId
|
|
31
|
-
* @param userSession
|
|
32
|
-
*/
|
|
33
|
-
export async function runWorkflowNotifyAction(workflowNotification: WorkflowNotification, recordId: any, userSession: any) {
|
|
34
|
-
if (_.isEmpty(workflowNotification) || _.isEmpty(recordId) || _.isEmpty(userSession)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
let record = await getObject(workflowNotification.object_name).findOne(recordId, null);
|
|
38
|
-
let objectName = workflowNotification.object_name;
|
|
39
|
-
let assignedUsers = workflowNotification.assigned_users;
|
|
40
|
-
let assignedUserField = workflowNotification.assigned_user_field;
|
|
41
|
-
let userId = userSession.userId;
|
|
42
|
-
let spaceId = userSession.spaceId;
|
|
43
|
-
|
|
44
|
-
let msgName = await computeFormula(workflowNotification.title, objectName, recordId, userId, spaceId);
|
|
45
|
-
let msgBody = await computeFormula(workflowNotification.body, objectName, recordId, userId, spaceId);
|
|
46
|
-
|
|
47
|
-
let message = {
|
|
48
|
-
name: msgName,
|
|
49
|
-
body: msgBody,
|
|
50
|
-
related_to: {
|
|
51
|
-
o: objectName,
|
|
52
|
-
ids: [record._id]
|
|
53
|
-
},
|
|
54
|
-
related_name: record.name,
|
|
55
|
-
from: userId,
|
|
56
|
-
space: spaceId
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
let to = [];
|
|
60
|
-
|
|
61
|
-
if (!_.isEmpty(assignedUsers)) {
|
|
62
|
-
to = to.concat(assignedUsers);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (!_.isEmpty(assignedUserField)) {
|
|
66
|
-
for (const userField of assignedUserField) {
|
|
67
|
-
if (record[userField]) {
|
|
68
|
-
to.push(record[userField]);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
to = _.uniq(_.flatten(to));
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* message: {name, body, related_to, related_name, from, space}
|
|
77
|
-
* from: userId
|
|
78
|
-
* to: [userId]
|
|
79
|
-
*/
|
|
80
|
-
Creator.addNotifications(message, userId, to);
|
|
81
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { getObject } from '../index';
|
|
2
|
-
import { computeFormula } from '../formula'
|
|
3
|
-
import { WorkflowRule } from './types/workflow_rule';
|
|
4
|
-
import { JsonMap } from "@salesforce/ts-types";
|
|
5
|
-
import { runFieldUpdateActions } from './field_updates'
|
|
6
|
-
import { FieldUpdateTarget } from './types/field_update_target';
|
|
7
|
-
import { runWorkflowNotifyActions } from './workflow_notifications'
|
|
8
|
-
import _ = require('underscore');
|
|
9
|
-
|
|
10
|
-
export type WorkflowRulesConfig = {
|
|
11
|
-
object_name: string,
|
|
12
|
-
event: string,
|
|
13
|
-
record: any,
|
|
14
|
-
user_session: any,
|
|
15
|
-
previous_record: any
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// 同一个流程规则触发的级联流程规则最大循环执行次数
|
|
19
|
-
const MAX_COUNT: number = 5;
|
|
20
|
-
|
|
21
|
-
export class WorkflowRulesRunner{
|
|
22
|
-
|
|
23
|
-
private object_name: string;
|
|
24
|
-
private event: string;
|
|
25
|
-
private record: any;
|
|
26
|
-
private user_session: any;
|
|
27
|
-
private previous_record: any;
|
|
28
|
-
private counter: any;
|
|
29
|
-
|
|
30
|
-
constructor(config: WorkflowRulesConfig){
|
|
31
|
-
this.object_name = config.object_name
|
|
32
|
-
this.event = config.event
|
|
33
|
-
this.record = config.record
|
|
34
|
-
this.user_session = config.user_session
|
|
35
|
-
this.previous_record = config.previous_record
|
|
36
|
-
this.counter = {};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async run(){
|
|
40
|
-
await this.runObjectWorkflowRules(this.object_name, this.event, this.record, this.user_session, this.previous_record);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async runObjectWorkflowRules(objectName, event, record, userSession, previousRecord, fromRuleId?){
|
|
44
|
-
if(!_.include(['insert', 'update'], event) || !record){
|
|
45
|
-
return ;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
let filters = [['object_name', '=', objectName], ['space', '=', record.space], ['active', '=', true]];
|
|
49
|
-
|
|
50
|
-
if(fromRuleId){
|
|
51
|
-
// 如果是级联触发的工作流规则,则要排除掉其原本来自的工作流规则,避免死循环
|
|
52
|
-
filters.push(['_id', '<>', fromRuleId]);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
switch (event) {
|
|
56
|
-
case 'insert':
|
|
57
|
-
filters.push([['trigger_type', '=', 'onCreateOnly'], 'or', ['trigger_type', '=', 'onAllChanges'], 'or', ['trigger_type', '=', 'onCreateOrTriggeringUpdate']])
|
|
58
|
-
break;
|
|
59
|
-
case 'update':
|
|
60
|
-
filters.push([['trigger_type', '=', 'onAllChanges'], 'or', ['trigger_type', '=', 'onCreateOrTriggeringUpdate']])
|
|
61
|
-
break;
|
|
62
|
-
default:
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let allTargets: Array<FieldUpdateTarget> = [];
|
|
67
|
-
let tempTargets: Array<FieldUpdateTarget> = [];
|
|
68
|
-
const wfRules = await getObject('workflow_rule').find({ filters: filters});
|
|
69
|
-
for (const wfRule of wfRules) {
|
|
70
|
-
if(wfRule.trigger_type === 'onCreateOrTriggeringUpdate'){
|
|
71
|
-
tempTargets = await runWFRule(wfRule, record, userSession, previousRecord)
|
|
72
|
-
}else{
|
|
73
|
-
tempTargets = await runWFRule(wfRule, record, userSession)
|
|
74
|
-
}
|
|
75
|
-
tempTargets.forEach((target) => {
|
|
76
|
-
target.from_rule_id = wfRule._id;
|
|
77
|
-
});
|
|
78
|
-
allTargets = allTargets.concat(tempTargets);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if(fromRuleId){
|
|
82
|
-
if(!this.counter[fromRuleId]){
|
|
83
|
-
this.counter[fromRuleId] = 0;
|
|
84
|
-
}
|
|
85
|
-
this.counter[fromRuleId]++;
|
|
86
|
-
if(this.counter[fromRuleId] > MAX_COUNT){
|
|
87
|
-
// 当同一个工作流规则反复多次循环级联调用时直接退出循环。
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
for (const target of allTargets) {
|
|
92
|
-
// 因为工作流操作可能更改记录字段值,所以这里只能根据id重新取record
|
|
93
|
-
const targetRecord = await getObject(target.object_name).findOne(target.record_id, null);
|
|
94
|
-
await this.runObjectWorkflowRules(target.object_name, event, targetRecord, userSession, target.previous_record, target.from_rule_id);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// export async function runObjectWorkflowRulesOnCreateOnly(objectName, record, userSession) {
|
|
100
|
-
// const wfRules = await getObject('workflow_rule').find({ filters: [['object_name', '=', objectName], ['space', '=', record.space], ['active', '=', true], ['trigger_type', '=', 'onCreateOnly']] });
|
|
101
|
-
// for (const wfRule of wfRules) {
|
|
102
|
-
// await runWFRule(wfRule, record, userSession)
|
|
103
|
-
// }
|
|
104
|
-
// }
|
|
105
|
-
|
|
106
|
-
// export async function runObjectWorkflowRulesOnAllChanges(objectName, record, userSession) {
|
|
107
|
-
// const wfRules = await getObject('workflow_rule').find({ filters: [['object_name', '=', objectName], ['space', '=', record.space], ['active', '=', true], ['trigger_type', '=', 'onAllChanges']] });
|
|
108
|
-
// for (const wfRule of wfRules) {
|
|
109
|
-
// await runWFRule(wfRule, record, userSession)
|
|
110
|
-
// }
|
|
111
|
-
// }
|
|
112
|
-
|
|
113
|
-
// export async function runObjectWorkflowRulesOnCreateOrTriggeringUpdate(objectName, record, userSession, previousRecord) {
|
|
114
|
-
// const wfRules = await getObject('workflow_rule').find({ filters: [['object_name', '=', objectName], ['space', '=', record.space], ['active', '=', true], ['trigger_type', '=', 'onCreateOrTriggeringUpdate']] });
|
|
115
|
-
// for (const wfRule of wfRules) {
|
|
116
|
-
// await runWFRule(wfRule, record, userSession, previousRecord)
|
|
117
|
-
// }
|
|
118
|
-
// }
|
|
119
|
-
|
|
120
|
-
async function runWFRule(rule: WorkflowRule, record: JsonMap, userSession, previousRecord?: JsonMap) {
|
|
121
|
-
let previousIsTrue = false;
|
|
122
|
-
let targets: Array<FieldUpdateTarget> = [];
|
|
123
|
-
|
|
124
|
-
if(previousRecord){
|
|
125
|
-
previousIsTrue = await computeFormula(rule.formula, rule.object_name, previousRecord, userSession?.userId, userSession?.spaceId);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if(!previousIsTrue){
|
|
129
|
-
let isTrue = await computeFormula(rule.formula, rule.object_name, record, userSession?.userId, userSession?.spaceId)
|
|
130
|
-
if (isTrue) {
|
|
131
|
-
targets = await runFieldUpdateActions(rule.updates_field_actions, record._id, userSession);
|
|
132
|
-
await runWorkflowNotifyActions(rule.workflow_notifications_actions, record._id, userSession);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return targets;
|
|
136
|
-
}
|
package/src/driver/driver.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author: sunhaolin@hotoa.com
|
|
3
|
-
* @Date: 2021-06-03 15:11:52
|
|
4
|
-
* @LastEditors: yinlianghui@steedos.com
|
|
5
|
-
* @LastEditTime: 2022-05-21 15:56:26
|
|
6
|
-
* @Description:
|
|
7
|
-
*/
|
|
8
|
-
import { Dictionary } from '@salesforce/ts-types';
|
|
9
|
-
import { SteedosQueryOptions, SteedosQueryFilters } from "../types/query";
|
|
10
|
-
import { SteedosIDType, SteedosObjectType } from "../types";
|
|
11
|
-
import { SteedosFieldDBType } from './fieldDBType';
|
|
12
|
-
|
|
13
|
-
export type SteedosDriverConfig = {
|
|
14
|
-
/**
|
|
15
|
-
* Connection url where perform connection to.
|
|
16
|
-
*/
|
|
17
|
-
readonly url?: string;
|
|
18
|
-
/**
|
|
19
|
-
* Database host.
|
|
20
|
-
*/
|
|
21
|
-
readonly host?: string;
|
|
22
|
-
/**
|
|
23
|
-
* Database host port.
|
|
24
|
-
*/
|
|
25
|
-
readonly port?: number;
|
|
26
|
-
/**
|
|
27
|
-
* Database username.
|
|
28
|
-
*/
|
|
29
|
-
readonly username?: string;
|
|
30
|
-
/**
|
|
31
|
-
* Database password.
|
|
32
|
-
*/
|
|
33
|
-
readonly password?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Database name to connect to.
|
|
36
|
-
*/
|
|
37
|
-
readonly database?: string;
|
|
38
|
-
/**
|
|
39
|
-
* Once you set domain, driver will connect to SQL Server using domain login.
|
|
40
|
-
*/
|
|
41
|
-
readonly domain?: string;
|
|
42
|
-
/**
|
|
43
|
-
* The timezone configured on the MySQL server.
|
|
44
|
-
* This is used to type cast server date/time values to JavaScript Date object and vice versa.
|
|
45
|
-
* This can be 'local', 'Z', or an offset in the form +HH:MM or -HH:MM. (Default: 'local')
|
|
46
|
-
*/
|
|
47
|
-
readonly timezone?: string;
|
|
48
|
-
/**
|
|
49
|
-
* Database options.
|
|
50
|
-
*/
|
|
51
|
-
readonly connectString?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Database options.
|
|
54
|
-
*/
|
|
55
|
-
readonly options?: any;
|
|
56
|
-
/**
|
|
57
|
-
* Print sql log for driver.
|
|
58
|
-
*/
|
|
59
|
-
readonly logging?: boolean | Array<any>;
|
|
60
|
-
/**
|
|
61
|
-
* collection locale.
|
|
62
|
-
*/
|
|
63
|
-
readonly locale?: string;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
export interface SteedosDriver {
|
|
70
|
-
|
|
71
|
-
//constructor(url:string): any;
|
|
72
|
-
// new(config: SteedosDriverConfig): any;
|
|
73
|
-
databaseVersion?: string;
|
|
74
|
-
config?: SteedosDriverConfig;
|
|
75
|
-
connect();
|
|
76
|
-
close();
|
|
77
|
-
getSupportedColumnTypes(): SteedosFieldDBType[];
|
|
78
|
-
find(tableName: string, query: SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
79
|
-
aggregate?(tableName: string, query: SteedosQueryOptions, externalPipeline: any, userId?: SteedosIDType): any;
|
|
80
|
-
findOne(tableName: string, id: SteedosIDType, query: SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
81
|
-
insert(tableName: string, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
82
|
-
update(tableName: string, id: SteedosIDType | SteedosQueryOptions, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
83
|
-
updateOne(tableName: string, id: SteedosIDType | SteedosQueryOptions, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
84
|
-
updateMany?(tableName: string, queryFilters: SteedosQueryFilters, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
85
|
-
delete(tableName: string, id: SteedosIDType | SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
86
|
-
directUpdate(tableName: string, id: SteedosIDType | SteedosQueryOptions, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
87
|
-
directFind(tableName: string, query: SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
88
|
-
directInsert(tableName: string, doc: Dictionary<any>, userId?: SteedosIDType): any;
|
|
89
|
-
directDelete(tableName: string, id: SteedosIDType | SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
90
|
-
directAggregate?(tableName: string, query: SteedosQueryOptions, externalPipeline: any, userId?: SteedosIDType): any;
|
|
91
|
-
directAggregatePrefixalPipeline?(tableName: string, query: SteedosQueryOptions, prefixalPipeline: any, userId?: SteedosIDType): any;
|
|
92
|
-
count(tableName: string, query: SteedosQueryOptions, userId?: SteedosIDType): any;
|
|
93
|
-
formatRecord?(doc: Dictionary<any>, objectConfig: SteedosObjectType): any;
|
|
94
|
-
dropEntities?(): any;
|
|
95
|
-
registerEntities?(objects: Dictionary<SteedosObjectType>): any;
|
|
96
|
-
dropTables?(): any;
|
|
97
|
-
createTables?(objects: Dictionary<SteedosObjectType>): any;
|
|
98
|
-
init(objects: Dictionary<SteedosObjectType>): any;
|
|
99
|
-
_makeNewID?(tableName?: string): any;
|
|
100
|
-
encryptValue?(value: any): any;
|
|
101
|
-
}
|
|
102
|
-
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author: sunhaolin@hotoa.com
|
|
3
|
-
* @Date: 2022-05-03 11:37:54
|
|
4
|
-
* @LastEditors: sunhaolin@hotoa.com
|
|
5
|
-
* @LastEditTime: 2022-05-13 14:00:37
|
|
6
|
-
* @Description:
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { Binary } from "mongodb";
|
|
10
|
-
import { parse } from 'mongodb-uri';
|
|
11
|
-
// var MY_LOCAL_KEY = crypto.randomBytes(96).toString('base64')
|
|
12
|
-
// 主密钥
|
|
13
|
-
const MY_LOCAL_KEY = process.env.STEEDOS_CSFLE_MASTER_KEY;
|
|
14
|
-
// 密钥管理服务
|
|
15
|
-
export function getKMSProviders() {
|
|
16
|
-
return {
|
|
17
|
-
"local": {
|
|
18
|
-
"key": new Binary(Buffer.from(MY_LOCAL_KEY, "base64"), 0)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const defaultuUriObj = parse(process.env.MONGO_URL);
|
|
24
|
-
// 密钥保管库库名
|
|
25
|
-
export const keyVaultDb = process.env.STEEDOS_CSFLE_KEY_VAULT_DB || defaultuUriObj.database; // 默认当前MONGO_URL的db
|
|
26
|
-
// 密钥保管库表名
|
|
27
|
-
export const keyVaultCollection = process.env.STEEDOS_CSFLE_KEY_VAULT_COLLECTION || '__keystore'; // 默认 __keystore
|
|
28
|
-
// 密钥保管库命名空间
|
|
29
|
-
export const keyVaultNamespace = `${keyVaultDb}.${keyVaultCollection}`;
|
|
30
|
-
// const connectionString = `mongodb+srv://${USER}:${PWD}@${HOST}/?retryWrites=true&w=majority`;
|
|
31
|
-
// 密钥保管库连接字符串
|
|
32
|
-
export const connectionString = process.env.STEEDOS_CSFLE_MONGO_URL || process.env.MONGO_URL; // 默认 MONGO_URL
|
|
33
|
-
// 主密钥别名
|
|
34
|
-
export const altKeyName = process.env.STEEDOS_CSFLE_ALT_KEY_NAME || 'steedos'; // 默认 steedos
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export enum SteedosFieldDBType {
|
|
2
|
-
varchar = 'varchar',
|
|
3
|
-
text = 'text',
|
|
4
|
-
number = 'number',
|
|
5
|
-
boolean = 'boolean',
|
|
6
|
-
date = 'date',
|
|
7
|
-
dateTime = 'dateTime',
|
|
8
|
-
json = 'json',
|
|
9
|
-
array = 'array',
|
|
10
|
-
// oneToOne,
|
|
11
|
-
// oneToMany,
|
|
12
|
-
// manyToOne,
|
|
13
|
-
// manyToMany
|
|
14
|
-
}
|
package/src/driver/format.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author: yinlianghui@steedos.com
|
|
3
|
-
* @Date: 2022-05-21 15:59:14
|
|
4
|
-
* @LastEditors: yinlianghui@steedos.com
|
|
5
|
-
* @LastEditTime: 2022-05-21 18:18:07
|
|
6
|
-
* @Description:
|
|
7
|
-
*/
|
|
8
|
-
import { Dictionary } from "@salesforce/ts-types";
|
|
9
|
-
import { SteedosObjectType } from "../types";
|
|
10
|
-
import _ = require('lodash');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* https://github.com/steedos/steedos-frontend/issues/69
|
|
14
|
-
* mongo数据源不会自动把日期/日期时间字段从字符串转换为Date类型
|
|
15
|
-
* https://github.com/steedos/steedos-platform/issues/3314
|
|
16
|
-
* 公式中可能引用日期/日期时间字段做比较,所以需要在object层就调用该函数,而不是在driver层调用
|
|
17
|
-
* Meteor数据源只是在driver层保存数据的时候会自动处理各种字段类型转换,所以也调用了该函数提前转换,以避免公式运算中拿到的参数值也是转换前的
|
|
18
|
-
* TypeORM相关的数据源因为一直没暴露过相关问题,所以暂时不调用该函数
|
|
19
|
-
* direct相关db操作函数因为可能从接口中接收记录doc参数值,所以也调用了该函数
|
|
20
|
-
* @param doc 记录数据
|
|
21
|
-
* @param objectConfig 对象schema
|
|
22
|
-
* @returns
|
|
23
|
-
*/
|
|
24
|
-
export function formatRecord(doc: Dictionary<any>, objectConfig: SteedosObjectType) {
|
|
25
|
-
if(!objectConfig){
|
|
26
|
-
return doc;
|
|
27
|
-
}
|
|
28
|
-
const fields = objectConfig.fields;
|
|
29
|
-
return _.mapValues(doc, function(value, key) {
|
|
30
|
-
let field = fields[key];
|
|
31
|
-
if(_.isString(value) && field && ["date", "datetime", "time"].indexOf(field.type) > -1){
|
|
32
|
-
return new Date(value);
|
|
33
|
-
}
|
|
34
|
-
return value;
|
|
35
|
-
});
|
|
36
|
-
}
|
package/src/driver/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author: sunhaolin@hotoa.com
|
|
3
|
-
* @Date: 2021-05-24 12:32:57
|
|
4
|
-
* @LastEditors: yinlianghui@steedos.com
|
|
5
|
-
* @LastEditTime: 2022-05-21 16:02:09
|
|
6
|
-
* @Description:
|
|
7
|
-
*/
|
|
8
|
-
export { SteedosDriver, SteedosDriverConfig } from "./driver"
|
|
9
|
-
|
|
10
|
-
export { SteedosMongoDriver } from "./mongo"
|
|
11
|
-
export { SteedosSqlite3Driver } from "./sqlite3"
|
|
12
|
-
export { SteedosSqlServerDriver } from "./sqlserver"
|
|
13
|
-
export { SteedosPostgresDriver } from "./postgres"
|
|
14
|
-
export { SteedosOracleDriver } from "./oracle"
|
|
15
|
-
export { SteedosMySqlDriver } from "./mysql"
|
|
16
|
-
export { SteedosMeteorMongoDriver } from "./meteorMongo"
|
|
17
|
-
export { SteedosFieldDBType } from './fieldDBType'
|
|
18
|
-
|
|
19
|
-
export * from './field-encrytion'
|
|
20
|
-
export * from './format'
|