@steedos/objectql 2.2.26 → 2.2.29

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.
@@ -5,14 +5,25 @@ import { getMD5, JSONStringify, transformListenersToTriggers } from '../util'
5
5
  import _ = require('lodash');
6
6
  var util = require('../util');
7
7
  var clone = require('clone');
8
+ import { _TRIGGERKEYS } from '../types';
8
9
 
9
10
  const _lazyLoadListeners: Dictionary<any> = {};
10
11
 
12
+ // 用于存放通配触发器,即listenTo的值是通配符
13
+ const _patternListerners: Dictionary<any> = {};
14
+
11
15
  const addLazyLoadListeners = function(objectName: string, json: SteedosListenerConfig){
12
16
  if(!_lazyLoadListeners[objectName]){
13
17
  _lazyLoadListeners[objectName] = []
14
18
  }
15
19
  _lazyLoadListeners[objectName].push(json)
20
+
21
+ if (isPatternListener(json)) {
22
+ if(!_patternListerners[objectName]){
23
+ _patternListerners[objectName] = []
24
+ }
25
+ _patternListerners[objectName].push(json)
26
+ }
16
27
  }
17
28
 
18
29
  export const getLazyLoadListeners = function(objectName?: string){
@@ -125,6 +136,23 @@ export const removePackageObjectTriggers = (serviceName: string)=>{
125
136
  // console.log(error)
126
137
  // }
127
138
  })
139
+
140
+ _.each(_patternListerners, (listeners, objectName)=>{
141
+ let objectConfig = getObjectConfig(objectName);
142
+ _patternListerners[objectName] = _.filter(listeners, function(listener: any) {
143
+ const drop = listener.metadataServiceName === serviceName;
144
+ if(drop){
145
+ try {
146
+ if(objectConfig && objectConfig.listeners){
147
+ delete objectConfig.listeners[listener.name]
148
+ }
149
+ } catch (error) {
150
+
151
+ }
152
+ }
153
+ return drop != true;
154
+ });
155
+ })
128
156
  }
129
157
 
130
158
  export const loadObjectTriggers = function (filePath: string, serviceName: string){
@@ -137,4 +165,72 @@ export const loadObjectTriggers = function (filePath: string, serviceName: strin
137
165
  triggers.push(addObjectListenerConfig(Object.assign(json, {metadataServiceName: serviceName})));
138
166
  })
139
167
  return triggers;
168
+ }
169
+
170
+ /**
171
+ * 判断是否通配触发器
172
+ * @param data
173
+ * @returns
174
+ */
175
+ function isPatternListener(data){
176
+ const {listenTo} = data;
177
+ if(listenTo === '*'){
178
+ return true;
179
+ }else if(_.isRegExp(listenTo)){
180
+ return true;
181
+ }else if(_.isString(listenTo) && listenTo.startsWith("/")){
182
+ try {
183
+ if(_.isRegExp(eval(listenTo))){
184
+ return true;
185
+ }
186
+ } catch (error) {
187
+ return false
188
+ }
189
+ return false;
190
+ }
191
+ return false;
192
+ }
193
+
194
+ /**
195
+ * 获取旧版触发器中写了通配符的触发器
196
+ * @param objectApiName
197
+ * @returns
198
+ */
199
+ export function getPatternListeners(objectApiName: string) {
200
+ let patternListeners = {};
201
+
202
+ const pushTrigger = (listeners: [any]) => {
203
+ for (const listener of listeners) {
204
+ _TRIGGERKEYS.forEach((key) => {
205
+ let event = listener[key];
206
+ if (_.isFunction(event)) {
207
+ patternListeners[listener.name] = listener;
208
+ }
209
+ })
210
+ }
211
+ }
212
+
213
+ _.each(_patternListerners, (listeners, objectName) => {
214
+ try {
215
+ if (objectName === '*') {
216
+ pushTrigger(listeners);
217
+ }
218
+ else if (_.isRegExp(objectName) && objectName.test(objectApiName)) {
219
+ pushTrigger(listeners);
220
+ }
221
+ else if (_.isString(objectName) && objectName.startsWith("/")) {
222
+ try {
223
+ if (_.isRegExp(eval(objectName)) && eval(objectName).test(objectApiName)) {
224
+ pushTrigger(listeners);
225
+ }
226
+ } catch (error) {
227
+ // DO NOTHING
228
+ }
229
+ }
230
+ } catch (error) {
231
+ console.log(`[getPatternListeners] `, error);
232
+ }
233
+ })
234
+
235
+ return patternListeners;
140
236
  }
@@ -33,20 +33,27 @@ export function generateActionGraphqlProp(actionName: string, objectConfig: Stee
33
33
  return gplObj;
34
34
  }
35
35
  switch (actionName) {
36
- case 'count':
36
+ case 'graphqlCount':
37
37
  gplObj.query = gql`
38
38
  type Query {
39
- ${objectName}__${actionName}(fields: JSON, filters: JSON, top: Int, skip: Int, sort: String): Int
39
+ ${objectName}__count(fields: JSON, filters: JSON, top: Int, skip: Int, sort: String): Int
40
40
  }
41
41
  `;
42
42
  break;
43
- case 'find':
43
+ case 'graphqlFind':
44
44
  gplObj.query = gql`
45
45
  type Query {
46
46
  ${objectName}(fields: JSON, filters: JSON, top: Int, skip: Int, sort: String): [${objectName}]
47
47
  }
48
48
  `;
49
49
  break;
50
+ case 'findOne':
51
+ gplObj.query = gql`
52
+ type Query {
53
+ ${objectName}__${actionName}(id: JSON): ${objectName}
54
+ }
55
+ `;
56
+ break;
50
57
  case 'insert':
51
58
  gplObj.mutation = gql`
52
59
  type Mutation {
@@ -1,11 +1,12 @@
1
1
  import { SteedosObjectType } from '../types/object';
2
- import { getDataSource } from '../types/datasource';
2
+ import { getDataSource, SteedosDatabaseDriverType } from '../types/datasource';
3
3
  import { getObjectConfig } from '../types/object_dynamic_load';
4
4
  import _ = require('underscore');
5
5
  import { generateActionRestProp, generateActionGraphqlProp, generateSettingsGraphql, RELATED_PREFIX, _getRelatedType, correctName, getGraphqlActions, getRelatedResolver, dealWithRelatedFields, getLocalService } from './helpers';
6
6
  import { getObjectServiceName } from '.';
7
7
  import { jsonToObject } from '../util/convert';
8
8
  import { extend } from '../util';
9
+ import { formatFiltersToODataQuery } from "@steedos/filters";
9
10
  const Future = require('fibers/future');
10
11
  import { getSteedosSchema } from '../';
11
12
  // import { parse } from '@steedos/formula';
@@ -194,6 +195,73 @@ function getObjectServiceActionsSchema() {
194
195
  return await this.aggregate(query, externalPipeline, userSession)
195
196
  }
196
197
  },
198
+ // meteor、default database 默认不返回is_deleted = true的数据
199
+ graphqlFind:{
200
+ params: {
201
+ fields: { type: 'array', items: "string", optional: true },
202
+ filters: [{ type: 'array', optional: true }, { type: 'string', optional: true }],
203
+ top: { type: 'number', optional: true },
204
+ skip: { type: 'number', optional: true },
205
+ sort: { type: 'string', optional: true }
206
+ },
207
+ async handler(ctx) {
208
+ //TODO filters: 如果filters中没有查询 is_deleted 则自动添加is_deleted != true 条件
209
+ if(this.object.datasource.driver === SteedosDatabaseDriverType.MeteorMongo || this.object.datasource.driver === SteedosDatabaseDriverType.Mongo){
210
+ const { filters } = ctx.params;
211
+ if (filters) {
212
+ if(_.isString(filters)){
213
+ if(filters.indexOf('(is_deleted eq true)') < 0){
214
+ ctx.params.filters = `(${filters}) and (is_deleted ne true)`;
215
+ }
216
+ }
217
+ if(_.isArray(filters)){
218
+ const filtersStr = formatFiltersToODataQuery(filters);
219
+ if(filtersStr.indexOf('(is_deleted eq true)') < 0){
220
+ ctx.params.filters.push(['is_deleted', '!=', true])
221
+ }
222
+ }
223
+ }else{
224
+ ctx.params.filters = '(is_deleted ne true)'
225
+ }
226
+ }
227
+
228
+ const userSession = ctx.meta.user;
229
+ return this.find(ctx.params, userSession)
230
+ }
231
+ },
232
+ graphqlCount:{
233
+ params: {
234
+ fields: { type: 'array', items: "string", optional: true },
235
+ filters: [{ type: 'array', optional: true }, { type: 'string', optional: true }],
236
+ top: { type: 'number', optional: true },
237
+ skip: { type: 'number', optional: true },
238
+ sort: { type: 'string', optional: true }
239
+ },
240
+ async handler(ctx) {
241
+ //TODO filters: 如果filters中没有查询 is_deleted 则自动添加is_deleted != true 条件
242
+ if(this.object.datasource.driver === SteedosDatabaseDriverType.MeteorMongo || this.object.datasource.driver === SteedosDatabaseDriverType.Mongo){
243
+ const { filters } = ctx.params;
244
+ if (filters) {
245
+ if(_.isString(filters)){
246
+ if(filters.indexOf('(is_deleted eq true)') < 0){
247
+ ctx.params.filters = `(${filters}) and (is_deleted ne true)`;
248
+ }
249
+ }
250
+ if(_.isArray(filters)){
251
+ const filtersStr = formatFiltersToODataQuery(filters);
252
+ if(filtersStr.indexOf('(is_deleted eq true)') < 0){
253
+ ctx.params.filters.push(['is_deleted', '!=', true])
254
+ }
255
+ }
256
+ }else{
257
+ ctx.params.filters = '(is_deleted ne true)'
258
+ }
259
+ }
260
+
261
+ const userSession = ctx.meta.user;
262
+ return this.count(ctx.params, userSession)
263
+ }
264
+ },
197
265
  find: {
198
266
  params: {
199
267
  fields: { type: 'array', items: "string", optional: true },
@@ -18,6 +18,7 @@ import { sortBy, forEach } from 'lodash';
18
18
  import { ShareRules } from './shareRule';
19
19
  import { RestrictionRule } from './restrictionRule';
20
20
  import { FieldPermission } from './field_permission';
21
+ import { getPatternListeners } from '../dynamic-load';
21
22
 
22
23
  const clone = require('clone')
23
24
 
@@ -113,7 +114,7 @@ export interface SteedosObjectTypeConfig extends SteedosObjectProperties {
113
114
  permission_set?: Dictionary<SteedosObjectPermissionTypeConfig> //TODO remove ; 目前为了兼容现有object的定义保留
114
115
  }
115
116
 
116
- const _TRIGGERKEYS = ['beforeFind', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterFind', 'afterCount', 'afterFindOne', 'afterInsert', 'afterUpdate', 'afterDelete', 'beforeAggregate', 'afterAggregate']
117
+ export const _TRIGGERKEYS = ['beforeFind', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterFind', 'afterCount', 'afterFindOne', 'afterInsert', 'afterUpdate', 'afterDelete', 'beforeAggregate', 'afterAggregate']
117
118
 
118
119
  const properties = ['label', 'icon', 'enable_search', 'sidebar', 'is_enable', 'enable_files', 'enable_tasks', 'enable_notes', 'enable_events', 'enable_api', 'enable_share', 'enable_instances', 'enable_chatter', 'enable_audit', 'enable_web_forms', 'enable_inline_edit', 'enable_approvals', 'enable_trash', 'enable_space_global', 'enable_tree', 'parent_field', 'children_field', 'enable_enhanced_lookup', 'enable_workflow', 'is_view', 'hidden', 'description', 'custom', 'owner', 'methods', '_id', 'relatedList', 'fields_serial_number', "is_enable", "in_development", "version"]
119
120
 
@@ -361,16 +362,35 @@ export class SteedosObjectType extends SteedosObjectProperties {
361
362
 
362
363
  async runTriggers(when: string, context: SteedosTriggerContextConfig) {
363
364
  let triggers = this._triggersQueue[when]
364
- if (!triggers) {
365
- return;
366
- }
365
+ if (triggers) {
366
+ let triggerKeys = _.keys(triggers)
367
367
 
368
- let triggerKeys = _.keys(triggers)
368
+ for (let index = 0; index < triggerKeys.length; index++) {
369
+ let trigger = triggers[triggerKeys[index]];
370
+ await this.runTirgger(trigger, context)
371
+ }
372
+ }
369
373
 
370
- for (let index = 0; index < triggerKeys.length; index++) {
371
- let trigger = triggers[triggerKeys[index]];
372
- await this.runTirgger(trigger, context)
374
+ // 获取通配的trigger,如果有则生成SteedosTriggerType执行
375
+ let wildcardListeners = getPatternListeners(this.name);
376
+ if (wildcardListeners) {
377
+ for (const key in wildcardListeners) {
378
+ if (Object.prototype.hasOwnProperty.call(wildcardListeners, key)) {
379
+ const listener = wildcardListeners[key];
380
+ if (listener && listener[when]) {
381
+ let triggerConfig: SteedosTriggerTypeConfig = {
382
+ name: `${key}_${when}`,
383
+ on: 'server',
384
+ when: when,
385
+ todo: listener[when],
386
+ }
387
+ let trigger = new SteedosTriggerType(triggerConfig)
388
+ await this.runTirgger(trigger, context)
389
+ }
390
+ }
391
+ }
373
392
  }
393
+
374
394
  }
375
395
 
376
396
  async runTriggerActions(when: string, context: SteedosTriggerContextConfig) {
@@ -1896,7 +1916,7 @@ export class SteedosObjectType extends SteedosObjectProperties {
1896
1916
  sharesFilter = getUserObjectSharesFilters(this.name, userSession);
1897
1917
 
1898
1918
  if (!_.isEmpty(companyFilter)) {
1899
- permissionFilters.push(`(${companyFilter.join(' and ')})`);
1919
+ permissionFilters.push(`(${companyFilter.join(' or ')})`);
1900
1920
  }
1901
1921
 
1902
1922
  if (ownerFilter) {