@live-change/relations-plugin 0.7.32 → 0.7.34

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.
@@ -0,0 +1,115 @@
1
+ const {extractObjectData} = require("./utils.js")
2
+ const App = require("@live-change/framework");
3
+ const {
4
+ TriggerDefinition
5
+ } = App
6
+
7
+ async function fireChangeTriggers(context, objectType, identifiers, object, oldData, data) {
8
+ const { service, modelName } = context
9
+ const changeType = data ? (oldData ? 'update' : 'create') : 'delete'
10
+ await Promise.all([
11
+ service.trigger({
12
+ type: changeType+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
13
+ objectType,
14
+ object,
15
+ identifiers,
16
+ data,
17
+ oldData
18
+ }),
19
+ service.trigger({
20
+ type: changeType+'Object',
21
+ objectType,
22
+ object,
23
+ identifiers,
24
+ data,
25
+ oldData
26
+ })
27
+ ])
28
+ }
29
+
30
+ async function triggerDeleteOnParentDeleteTriggers(
31
+ context, propertyName, path, objectType, object, emit) {
32
+ const {
33
+ service, modelRuntime, identifiers, objectType: myType, writeableProperties, modelName,
34
+ reverseRelationWord
35
+ } = context
36
+ const indexName = 'by' + propertyName[0].toUpperCase() + propertyName.slice(1)
37
+ const bucketSize = 32
38
+ let found = false
39
+ let bucket
40
+ let gt = ''
41
+ do {
42
+ const bucket = await modelRuntime.sortedIndexRangeGet(indexName, path, {
43
+ gt,
44
+ limit: bucketSize
45
+ })
46
+ if (bucket.length > 0) found = true
47
+ gt = bucket[bucket.length - 1].id
48
+ const deleteTriggerPromises = bucket.map(entity => {
49
+ return (async () => {
50
+ await fireChangeTriggers(context, myType, identifiers, entity.to,
51
+ extractObjectData(writeableProperties, entity, {}), null)
52
+ })()
53
+ })
54
+ await Promise.all(deleteTriggerPromises)
55
+ } while (bucket.length == bucketSize)
56
+ if (found) {
57
+ const eventName = propertyName + reverseRelationWord + modelName + 'DeleteByOwner'
58
+ emit({
59
+ type: eventName,
60
+ ownerType: objectType,
61
+ owner: object
62
+ })
63
+ }
64
+ }
65
+
66
+ function registerParentDeleteTriggers(context, config) {
67
+ const {
68
+ service, parentsTypes, otherPropertyNames,
69
+ } = context
70
+ if(parentsTypes) {
71
+ for (const index in parentsTypes) {
72
+ const otherType = parentsTypes[index]
73
+ const propertyName = otherPropertyNames[index]
74
+ const triggerName = 'delete' + otherType[0].toUpperCase() + otherType.slice(1)
75
+ if (!service.triggers[triggerName]) service.triggers[triggerName] = []
76
+ service.triggers[triggerName].push(new TriggerDefinition({
77
+ name: triggerName,
78
+ properties: {
79
+ object: {
80
+ type: String
81
+ }
82
+ },
83
+ async execute({object}, {client, service}, emit) {
84
+ await triggerDeleteOnParentDeleteTriggers(context, propertyName, [object],
85
+ otherType, object, emit)
86
+ }
87
+ }))
88
+ }
89
+ } else {
90
+ const triggerName = 'deleteObject'
91
+ if(!service.triggers[triggerName]) service.triggers[triggerName] = []
92
+ service.triggers[triggerName].push(new TriggerDefinition({
93
+ name: triggerName,
94
+ properties: {
95
+ objectType: {
96
+ type: String,
97
+ },
98
+ object: {
99
+ type: String
100
+ }
101
+ },
102
+ async execute({ objectType, object }, {client, service}, emit) {
103
+ for(const propertyName of otherPropertyNames) {
104
+ await triggerDeleteOnParentDeleteTriggers(context, propertyName, [objectType, object],
105
+ objectType, object, emit)
106
+ }
107
+ }
108
+ }))
109
+ }
110
+ }
111
+
112
+ module.exports = {
113
+ fireChangeTriggers,
114
+ registerParentDeleteTriggers
115
+ }
package/entity.js CHANGED
@@ -3,6 +3,7 @@ const {
3
3
  processModelsAnnotation, extractIdParts, extractIdentifiers, extractObjectData
4
4
  } = require('./utils.js')
5
5
  const App = require("@live-change/framework")
6
+ const {fireChangeTriggers} = require("./changeTriggers.js");
6
7
  const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
7
8
 
8
9
  const annotation = 'entity'
@@ -16,7 +17,7 @@ function entityAccessControl({service, modelName, modelPropertyName}, accessCont
16
17
  }
17
18
 
18
19
  function defineView(config, context) {
19
- const { service, modelRuntime, modelPropertyName, modelName, others, model } = context
20
+ const { service, modelRuntime, modelPropertyName, modelName, model } = context
20
21
  const viewName = (config.prefix || '' ) + (config.prefix ? modelName : modelPropertyName) + (config.suffix || '')
21
22
  service.views[viewName] = new ViewDefinition({
22
23
  name: viewName,
@@ -84,7 +85,7 @@ function defineDeletedEvent(config, context) {
84
85
 
85
86
  function defineCreateAction(config, context) {
86
87
  const {
87
- service, app, model, defaults, modelPropertyName, modelRuntime,
88
+ service, app, model, defaults, modelPropertyName, modelRuntime, objectType,
88
89
  modelName, writeableProperties
89
90
  } = context
90
91
  const eventName = modelName + 'Created'
@@ -106,6 +107,9 @@ function defineCreateAction(config, context) {
106
107
  const data = extractObjectData(writeableProperties, properties, defaults)
107
108
  await App.validation.validate({ ...data }, validators,
108
109
  { source: action, action, service, app, client })
110
+
111
+ await fireChangeTriggers(context, objectType, null, id,
112
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
109
113
  emit({
110
114
  type: eventName,
111
115
  [modelPropertyName]: id,
@@ -120,7 +124,7 @@ function defineCreateAction(config, context) {
120
124
 
121
125
  function defineUpdateAction(config, context) {
122
126
  const {
123
- service, app, model, modelRuntime, modelPropertyName,
127
+ service, app, model, modelRuntime, modelPropertyName, objectType,
124
128
  modelName, writeableProperties
125
129
  } = context
126
130
  const eventName = modelName + 'Updated'
@@ -145,6 +149,8 @@ function defineUpdateAction(config, context) {
145
149
  const data = extractObjectData(writeableProperties, properties, entity)
146
150
  await App.validation.validate({ ...identifiers, ...data }, validators,
147
151
  { source: action, action, service, app, client })
152
+ await fireChangeTriggers(context, null, id,
153
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
148
154
  emit({
149
155
  type: eventName,
150
156
  [modelPropertyName]: id,
@@ -158,8 +164,8 @@ function defineUpdateAction(config, context) {
158
164
 
159
165
  function defineDeleteAction(config, context) {
160
166
  const {
161
- service, app, model, modelRuntime, modelPropertyName,
162
- otherPropertyNames, modelName,
167
+ service, app, model, modelRuntime, modelPropertyName, objectType,
168
+ otherPropertyNames, modelName, writeableProperties,
163
169
  } = context
164
170
  const eventName = modelName + 'Deleted'
165
171
  const actionName = 'delete' + modelName
@@ -179,18 +185,8 @@ function defineDeleteAction(config, context) {
179
185
  const id = properties[modelPropertyName]
180
186
  const entity = await modelRuntime().get(id)
181
187
  if(!entity) throw new Error('not_found')
182
- await Promise.all([
183
- service.trigger({
184
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
185
- objectType: service.name+'_'+modelName,
186
- object: id
187
- }),
188
- service.trigger({
189
- type: 'deleteObject',
190
- objectType: service.name+'_'+modelName,
191
- object: id
192
- })
193
- ])
188
+ await fireChangeTriggers(context, objectType, null, id,
189
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, null)
194
190
  emit({
195
191
  type: eventName,
196
192
  [modelPropertyName]: id
@@ -226,10 +222,11 @@ module.exports = function(service, app) {
226
222
 
227
223
  const writeableProperties = modelProperties || config.writeableProperties
228
224
  //console.log("PPP", others)
225
+ const objectType = service.name + '_' + modelName
229
226
 
230
227
  const context = {
231
228
  service, app, model, originalModelProperties, modelProperties, modelPropertyName, defaults, modelRuntime,
232
- modelName, writeableProperties, annotation
229
+ modelName, writeableProperties, annotation, objectType
233
230
  }
234
231
 
235
232
  if (config.readAccess || config.readAccessControl || config.writeAccessControl) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/relations-plugin",
3
- "version": "0.7.32",
3
+ "version": "0.7.34",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,8 +21,8 @@
21
21
  "url": "https://www.viamage.com/"
22
22
  },
23
23
  "dependencies": {
24
- "@live-change/framework": "^0.7.32",
24
+ "@live-change/framework": "^0.7.34",
25
25
  "pluralize": "^8.0.0"
26
26
  },
27
- "gitHead": "e2f78f57b5d456851eb2dea56b25ac9133a3c909"
27
+ "gitHead": "730c14caf86069665193ce157b2663358abef342"
28
28
  }
@@ -1,9 +1,11 @@
1
1
  const App = require("@live-change/framework")
2
2
  const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
3
  const { extractTypeAndIdParts, extractIdentifiersWithTypes, prepareAccessControl } = require("./utilsAny.js")
4
- const { extractObjectData } = require("./utils.js")
4
+ const { extractObjectData, extractIdentifiers} = require("./utils.js")
5
5
  const { extractRange } = App
6
6
 
7
+ const { fireChangeTriggers } = require("./changeTriggers.js")
8
+
7
9
  const pluralize = require('pluralize')
8
10
 
9
11
  function defineView(config, context) {
@@ -49,7 +51,7 @@ function defineView(config, context) {
49
51
 
50
52
  function defineCreateAction(config, context) {
51
53
  const {
52
- service, app, model, defaults, modelPropertyName, modelRuntime,
54
+ service, app, model, defaults, modelPropertyName, modelRuntime, objectType,
53
55
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
54
56
  } = context
55
57
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Created'
@@ -74,6 +76,7 @@ function defineCreateAction(config, context) {
74
76
  const data = extractObjectData(writeableProperties, properties, defaults)
75
77
  await App.validation.validate({ ...identifiers, ...data }, validators,
76
78
  { source: action, action, service, app, client })
79
+ await fireChangeTriggers(context, objectType, identifiers, id, null, data)
77
80
  emit({
78
81
  type: eventName,
79
82
  [modelPropertyName]: id,
@@ -88,7 +91,7 @@ function defineCreateAction(config, context) {
88
91
 
89
92
  function defineUpdateAction(config, context) {
90
93
  const {
91
- service, app, model, modelRuntime, modelPropertyName,
94
+ service, app, model, modelRuntime, modelPropertyName, objectType,
92
95
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
93
96
  } = context
94
97
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
@@ -123,6 +126,8 @@ function defineUpdateAction(config, context) {
123
126
  const data = extractObjectData(writeableProperties, properties, entity)
124
127
  await App.validation.validate({ ...identifiers, ...data }, validators,
125
128
  { source: action, action, service, app, client })
129
+ await fireChangeTriggers(context, objectType, identifiers, id,
130
+ extractObjectData(writeableProperties, entity, {}), data)
126
131
  emit({
127
132
  type: eventName,
128
133
  [modelPropertyName]: id,
@@ -137,7 +142,7 @@ function defineUpdateAction(config, context) {
137
142
 
138
143
  function defineDeleteAction(config, context) {
139
144
  const {
140
- service, app, model, modelRuntime, modelPropertyName, identifiers,
145
+ service, app, model, modelRuntime, modelPropertyName, identifiers, objectType,
141
146
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
142
147
  } = context
143
148
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Deleted'
@@ -164,21 +169,12 @@ function defineDeleteAction(config, context) {
164
169
  if(!entity) throw new Error('not_found')
165
170
  const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
166
171
  const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
172
+ const identifiers = extractIdentifiers(otherPropertyNames, entity)
167
173
  if(JSON.stringify(entityTypeAndIdParts) != JSON.stringify(typeAndIdParts)) {
168
174
  throw new Error('not_authorized')
169
175
  }
170
- await Promise.all([
171
- service.trigger({
172
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
173
- objectType: service.name+'_'+modelName,
174
- object: id
175
- }),
176
- service.trigger({
177
- type: 'deleteObject',
178
- objectType: service.name+'_'+modelName,
179
- object: id
180
- })
181
- ])
176
+ await fireChangeTriggers(context, objectType, identifiers, id,
177
+ extractObjectData(writeableProperties, entity, {}), null)
182
178
  emit({
183
179
  type: eventName,
184
180
  [modelPropertyName]: id
@@ -3,6 +3,7 @@ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition }
3
3
  const { extractIdParts, extractIdentifiers, extractObjectData, prepareAccessControl } = require("./utils.js")
4
4
 
5
5
  const pluralize = require('pluralize')
6
+ const {fireChangeTriggers} = require("./changeTriggers.js")
6
7
 
7
8
  function defineView(config, context) {
8
9
  const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
@@ -43,7 +44,7 @@ function defineView(config, context) {
43
44
 
44
45
  function defineCreateAction(config, context) {
45
46
  const {
46
- service, app, model, defaults, modelPropertyName, modelRuntime,
47
+ service, app, model, defaults, modelPropertyName, modelRuntime, objectType,
47
48
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
48
49
  } = context
49
50
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Created'
@@ -68,6 +69,7 @@ function defineCreateAction(config, context) {
68
69
  const data = extractObjectData(writeableProperties, properties, defaults)
69
70
  await App.validation.validate({ ...identifiers, ...data }, validators,
70
71
  { source: action, action, service, app, client })
72
+ await fireChangeTriggers(context, objectType, identifiers, id, null, data)
71
73
  emit({
72
74
  type: eventName,
73
75
  [modelPropertyName]: id,
@@ -82,7 +84,7 @@ function defineCreateAction(config, context) {
82
84
 
83
85
  function defineUpdateAction(config, context) {
84
86
  const {
85
- service, app, model, modelRuntime, modelPropertyName,
87
+ service, app, model, modelRuntime, modelPropertyName, objectType,
86
88
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
87
89
  } = context
88
90
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
@@ -92,6 +94,10 @@ function defineUpdateAction(config, context) {
92
94
  service.actions[actionName] = new ActionDefinition({
93
95
  name: actionName,
94
96
  properties: {
97
+ [modelPropertyName]: {
98
+ type: model,
99
+ validation: ['nonEmpty']
100
+ },
95
101
  ...(model.properties)
96
102
  },
97
103
  access: config.updateAccess || config.writeAccess,
@@ -100,6 +106,7 @@ function defineUpdateAction(config, context) {
100
106
  //queuedBy: otherPropertyNames,
101
107
  waitForEvents: true,
102
108
  async execute(properties, { client, service }, emit) {
109
+ console.log("UPDATE", actionName, properties)
103
110
  const id = properties[modelPropertyName]
104
111
  const entity = await modelRuntime().get(id)
105
112
  if(!entity) throw 'not_found'
@@ -110,8 +117,11 @@ function defineUpdateAction(config, context) {
110
117
  }
111
118
  const identifiers = extractIdentifiers(otherPropertyNames, properties)
112
119
  const data = extractObjectData(writeableProperties, properties, entity)
113
- await App.validation.validate({ ...identifiers, ...data }, validators,
120
+ const dataWithIdentifiers = { [modelPropertyName]: id, ...identifiers, ...data }
121
+ await App.validation.validate(dataWithIdentifiers, validators,
114
122
  { source: action, action, service, app, client })
123
+ await fireChangeTriggers(context, objectType, identifiers, id,
124
+ extractObjectData(writeableProperties, entity, {}), data)
115
125
  emit({
116
126
  type: eventName,
117
127
  [modelPropertyName]: id,
@@ -126,7 +136,7 @@ function defineUpdateAction(config, context) {
126
136
 
127
137
  function defineDeleteAction(config, context) {
128
138
  const {
129
- service, app, model, modelRuntime, modelPropertyName,
139
+ service, app, model, modelRuntime, modelPropertyName, objectType,
130
140
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
131
141
  } = context
132
142
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Deleted'
@@ -136,6 +146,10 @@ function defineDeleteAction(config, context) {
136
146
  service.actions[actionName] = new ActionDefinition({
137
147
  name: actionName,
138
148
  properties: {
149
+ [modelPropertyName]: {
150
+ type: model,
151
+ validation: ['nonEmpty']
152
+ },
139
153
  ...(model.properties)
140
154
  },
141
155
  access: config.deleteAccess || config.writeAccess,
@@ -149,21 +163,12 @@ function defineDeleteAction(config, context) {
149
163
  if(!entity) throw new Error('not_found')
150
164
  const entityIdParts = extractIdParts(otherPropertyNames, entity)
151
165
  const idParts = extractIdParts(otherPropertyNames, properties)
166
+ const identifiers = extractIdentifiers(otherPropertyNames, entity)
152
167
  if(JSON.stringify(entityIdParts) != JSON.stringify(idParts)) {
153
168
  throw new Error('not_authorized')
154
169
  }
155
- await Promise.all([
156
- service.trigger({
157
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
158
- objectType: service.name+'_'+modelName,
159
- object: id
160
- }),
161
- service.trigger({
162
- type: 'deleteObject',
163
- objectType: service.name+'_'+modelName,
164
- object: id
165
- })
166
- ])
170
+ await fireChangeTriggers(context, objectType, identifiers, id,
171
+ extractObjectData(writeableProperties, entity, {}), null)
167
172
  emit({
168
173
  type: eventName,
169
174
  [modelPropertyName]: id
@@ -5,6 +5,7 @@ const { extractObjectData } = require("./utils.js")
5
5
  const { allCombinations } = require("./combinations.js")
6
6
 
7
7
  const pluralize = require('pluralize')
8
+ const {fireChangeTriggers} = require("./changeTriggers.js");
8
9
 
9
10
  function createIdentifiersProperties(keys) {
10
11
  const identifiers = {}
@@ -92,7 +93,7 @@ function defineRangeViews(config, context) {
92
93
 
93
94
  function defineSetAction(config, context) {
94
95
  const {
95
- service, app, model, defaults,
96
+ service, app, model, defaults, objectType,
96
97
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
97
98
  } = context
98
99
 
@@ -115,6 +116,7 @@ function defineSetAction(config, context) {
115
116
  const data = extractObjectData(writeableProperties, properties, defaults)
116
117
  await App.validation.validate({ ...identifiers, ...data }, validators,
117
118
  { source: action, action, service, app, client })
119
+ await fireChangeTriggers(context, objectType, identifiers, id, null, data)
118
120
  emit({
119
121
  type: eventName,
120
122
  identifiers, data
@@ -127,7 +129,7 @@ function defineSetAction(config, context) {
127
129
 
128
130
  function defineUpdateAction(config, context) {
129
131
  const {
130
- service, app, model, modelRuntime,
132
+ service, app, model, modelRuntime, objectType,
131
133
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
132
134
  } = context
133
135
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
@@ -152,6 +154,8 @@ function defineUpdateAction(config, context) {
152
154
  const data = extractObjectData(writeableProperties, properties, entity)
153
155
  await App.validation.validate({ ...identifiers, ...data }, validators,
154
156
  { source: action, action, service, app, client })
157
+ await fireChangeTriggers(context, objectType, identifiers, id,
158
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
155
159
  emit({
156
160
  type: eventName,
157
161
  identifiers, data
@@ -164,7 +168,7 @@ function defineUpdateAction(config, context) {
164
168
 
165
169
  function defineSetOrUpdateAction(config, context) {
166
170
  const {
167
- service, app, model, modelRuntime, defaults,
171
+ service, app, model, modelRuntime, defaults, objectType,
168
172
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
169
173
  } = context
170
174
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
@@ -188,6 +192,8 @@ function defineSetOrUpdateAction(config, context) {
188
192
  const data = extractObjectData(writeableProperties, properties, { ...defaults, ...entity } )
189
193
  await App.validation.validate({ ...identifiers, ...data }, validators,
190
194
  { source: action, action, service, app, client })
195
+ await fireChangeTriggers(context, objectType, identifiers, id,
196
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
191
197
  emit({
192
198
  type: eventName,
193
199
  identifiers, data
@@ -200,7 +206,7 @@ function defineSetOrUpdateAction(config, context) {
200
206
 
201
207
  function defineResetAction(config, context) {
202
208
  const {
203
- service, modelRuntime, modelPropertyName, identifiers,
209
+ service, modelRuntime, modelPropertyName, identifiers, objectType,
204
210
  otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model
205
211
  } = context
206
212
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Reset'
@@ -225,18 +231,8 @@ function defineResetAction(config, context) {
225
231
  const id = generateAnyId(otherPropertyNames, properties)
226
232
  const entity = await modelRuntime().get(id)
227
233
  if (!entity) throw new Error('not_found')
228
- await Promise.all([
229
- service.trigger({
230
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
231
- objectType: service.name+'_'+modelName,
232
- object: id
233
- }),
234
- service.trigger({
235
- type: 'deleteObject',
236
- objectType: service.name+'_'+modelName,
237
- object: id
238
- })
239
- ])
234
+ await fireChangeTriggers(context, objectType, identifiers, id,
235
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, null)
240
236
  emit({
241
237
  type: eventName,
242
238
  identifiers
@@ -3,6 +3,7 @@ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition }
3
3
  const {
4
4
  extractIdentifiers, extractObjectData, generateId, extractIdParts, prepareAccessControl
5
5
  } = require("./utils.js")
6
+ const {fireChangeTriggers} = require("./changeTriggers.js");
6
7
 
7
8
  function defineView(config, context) {
8
9
  const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
@@ -39,7 +40,7 @@ function defineView(config, context) {
39
40
 
40
41
  function defineSetAction(config, context) {
41
42
  const {
42
- service, app, model, defaults,
43
+ service, app, model, defaults, objectType,
43
44
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
44
45
  } = context
45
46
  const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Set'
@@ -57,10 +58,13 @@ function defineSetAction(config, context) {
57
58
  queuedBy: otherPropertyNames,
58
59
  waitForEvents: true,
59
60
  async execute(properties, { client, service }, emit) {
61
+ const idParts = extractIdParts(otherPropertyNames, properties)
62
+ const id = idParts.length > 1 ? idParts.map(p => JSON.stringify(p)).join(':') : idParts[0]
60
63
  const identifiers = extractIdentifiers(otherPropertyNames, properties)
61
64
  const data = extractObjectData(writeableProperties, properties, defaults)
62
65
  await App.validation.validate({ ...identifiers, ...data }, validators,
63
66
  { source: action, action, service, app, client })
67
+ await fireChangeTriggers(context, objectType, identifiers, id, null, data)
64
68
  emit({
65
69
  type: eventName,
66
70
  identifiers, data
@@ -73,7 +77,7 @@ function defineSetAction(config, context) {
73
77
 
74
78
  function defineUpdateAction(config, context) {
75
79
  const {
76
- service, app, model, modelRuntime,
80
+ service, app, model, modelRuntime, objectType,
77
81
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
78
82
  } = context
79
83
  const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
@@ -98,6 +102,9 @@ function defineUpdateAction(config, context) {
98
102
  const data = extractObjectData(writeableProperties, properties, entity)
99
103
  await App.validation.validate({ ...identifiers, ...data }, validators,
100
104
  { source: action, action, service, app, client })
105
+ const oldData = extractObjectData(writeableProperties, entity, {})
106
+ await fireChangeTriggers(context, objectType, identifiers, id,
107
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
101
108
  emit({
102
109
  type: eventName,
103
110
  identifiers, data
@@ -110,7 +117,7 @@ function defineUpdateAction(config, context) {
110
117
 
111
118
  function defineSetOrUpdateAction(config, context) {
112
119
  const {
113
- service, app, model, defaults, modelRuntime,
120
+ service, app, model, defaults, modelRuntime, objectType,
114
121
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
115
122
  } = context
116
123
  const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
@@ -134,6 +141,8 @@ function defineSetOrUpdateAction(config, context) {
134
141
  const data = extractObjectData(writeableProperties, properties, { ...defaults, ...entity })
135
142
  await App.validation.validate({ ...identifiers, ...data }, validators,
136
143
  { source: action, action, service, app, client })
144
+ await fireChangeTriggers(context, objectType, identifiers, id,
145
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, data)
137
146
  emit({
138
147
  type: eventName,
139
148
  identifiers, data
@@ -146,8 +155,8 @@ function defineSetOrUpdateAction(config, context) {
146
155
 
147
156
  function defineResetAction(config, context) {
148
157
  const {
149
- service, modelRuntime, modelPropertyName,
150
- otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model, others
158
+ service, modelRuntime, modelPropertyName, objectType,
159
+ otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model, others, writeableProperties
151
160
  } = context
152
161
  const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Reset'
153
162
  const actionName = 'reset' + joinedOthersClassName + 'Owned' + modelName
@@ -170,18 +179,8 @@ function defineResetAction(config, context) {
170
179
  const id = generateId(otherPropertyNames, properties)
171
180
  const entity = await modelRuntime().get(id)
172
181
  if (!entity) throw new Error('not_found')
173
- await Promise.all([
174
- service.trigger({
175
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
176
- objectType: service.name+'_'+modelName,
177
- object: id
178
- }),
179
- service.trigger({
180
- type: 'deleteObject',
181
- objectType: service.name+'_'+modelName,
182
- object: id
183
- })
184
- ])
182
+ await fireChangeTriggers(context, objectType, identifiers, id,
183
+ entity ? extractObjectData(writeableProperties, entity, {}) : null, null)
185
184
  emit({
186
185
  type: eventName,
187
186
  identifiers
package/utils.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const App = require("@live-change/framework")
2
2
  const app = App.app()
3
- const { allCombinations } = require("./combinations.js");
3
+ const { allCombinations } = require("./combinations.js")
4
+ const { fireChangeTriggers, registerParentDeleteTriggers } = require("./changeTriggers.js")
4
5
  const {
5
6
  PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition, TriggerDefinition
6
7
  } = App
@@ -113,16 +114,18 @@ function processModelsAnnotation(service, app, annotation, multiple, cb) {
113
114
  const others = what.map(other => other.getTypeName ? other.getTypeName() : (other.name ? other.name : other))
114
115
 
115
116
  const writeableProperties = modelProperties || config.writeableProperties
116
- //console.log("PPP", others)
117
- const otherPropertyNames = what.map(other => other.name ? other.name : other)
118
- const joinedOthersPropertyName = (otherPropertyNames[0][0].toLowerCase() + otherPropertyNames[0].slice(1)) +
119
- (others.length > 1 ? ('And' + others.slice(1).join('And')) : '')
120
- const joinedOthersClassName = others.join('And')
117
+ const otherNames = what.map(other => other.name ? other.name : other)
118
+ const otherPropertyNames = otherNames.map(name => name[0].toLowerCase() + name.slice(1))
119
+
120
+ const joinedOthersPropertyName = (otherNames[0][0].toLowerCase() + otherNames[0].slice(1)) +
121
+ (otherNames.length > 1 ? ('And' + otherNames.slice(1).join('And')) : '')
122
+ const joinedOthersClassName = otherNames.join('And')
123
+ const objectType = service.name + '_' + modelName
121
124
 
122
125
  const context = {
123
126
  service, app, model, originalModelProperties, modelProperties, modelPropertyName, defaults, modelRuntime,
124
127
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName,
125
- others, annotation
128
+ others, annotation, objectType, parentsType: others
126
129
  }
127
130
 
128
131
  cb(config, context)
@@ -188,62 +191,7 @@ function defineDeleteByOwnerEvents(config, context, generateId) {
188
191
  }
189
192
 
190
193
  function defineParentDeleteTriggers(config, context) {
191
- const {
192
- service, modelRuntime, modelPropertyName, identifiers, others,
193
- otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model,
194
- reverseRelationWord
195
- } = context
196
- for(const index in others) {
197
- const otherType = others[index]
198
- const propertyName = otherPropertyNames[index]
199
- const triggerName = 'delete' + otherType[0].toUpperCase() + otherType.slice(1)
200
- if(!service.triggers[triggerName]) service.triggers[triggerName] = []
201
- service.triggers[triggerName].push(new TriggerDefinition({
202
- name: triggerName,
203
- properties: {
204
- object: {
205
- type: String
206
- }
207
- },
208
- async execute({ object }, {client, service}, emit) {
209
- const tableName = modelRuntime().tableName
210
- const prefix = JSON.stringify(object)
211
- const indexName = tableName + 'by' + propertyName[0].toUpperCase() + propertyName.slice(1)
212
- const bucketSize = 32
213
- let found = false
214
- let bucket
215
- do {
216
- bucket = await app.dao.get(['database', 'indexRange', app.databaseName, indexName, {
217
- gte: prefix + ':',
218
- lte: prefix + '_\xFF\xFF\xFF\xFF',
219
- limit: bucketSize
220
- }])
221
- if(bucket.length > 0) found = true
222
- const deleteTriggerPromises = bucket.map(({to}) => [
223
- service.trigger({
224
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
225
- objectType: service.name+'_'+modelName,
226
- object: to
227
- }),
228
- service.trigger({
229
- type: 'deleteObject',
230
- objectType: service.name+'_'+modelName,
231
- object: to
232
- })
233
- ]).flat()
234
- await Promise.all(deleteTriggerPromises)
235
- } while (bucket.length == bucketSize)
236
- if(found) {
237
- const eventName = propertyName + reverseRelationWord + modelName + 'DeleteByOwner'
238
- emit({
239
- type: eventName,
240
- owner: object
241
- })
242
- }
243
- await Promise.all(promises)
244
- }
245
- }))
246
- }
194
+ registerParentDeleteTriggers(context, config)
247
195
  }
248
196
 
249
197
  module.exports = {
package/utilsAny.js CHANGED
@@ -4,6 +4,8 @@ const {
4
4
  PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition, TriggerDefinition
5
5
  } = App
6
6
  const { allCombinations } = require("./combinations.js")
7
+ const {fireChangeTriggers, registerParentDeleteTriggers} = require("./changeTriggers");
8
+ const {extractObjectData} = require("./utils.js");
7
9
 
8
10
  function extractTypeAndIdParts(otherPropertyNames, properties) {
9
11
  const typeAndIdParts = []
@@ -115,10 +117,14 @@ function processModelsAnyAnnotation(service, app, annotation, multiple, cb) {
115
117
  const joinedOthersPropertyName = otherPropertyNames[0] +
116
118
  (others.length > 1 ? ('And' + others.slice(1).join('And')) : '')
117
119
  const joinedOthersClassName = others.join('And')
120
+ const objectType = service.name + '_' + modelName
121
+
122
+ const { parentsTypes } = config
118
123
 
119
124
  const context = {
120
125
  service, app, model, originalModelProperties, modelProperties, modelPropertyName, defaults, modelRuntime,
121
- otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
126
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others,
127
+ objectType, parentsTypes
122
128
  }
123
129
 
124
130
  cb(config, context)
@@ -183,64 +189,7 @@ function defineDeleteByOwnerEvents(config, context, generateId) {
183
189
  }
184
190
 
185
191
  function defineParentDeleteTrigger(config, context) {
186
- const {
187
- service, modelRuntime, modelPropertyName, identifiers,
188
- otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model,
189
- reverseRelationWord
190
- } = context
191
- const triggerName = 'deleteObject'
192
- if(!service.triggers[triggerName]) service.triggers[triggerName] = []
193
- service.triggers[triggerName].push(new TriggerDefinition({
194
- name: triggerName,
195
- properties: {
196
- objectType: {
197
- type: String,
198
- },
199
- object: {
200
- type: String
201
- }
202
- },
203
- async execute({ objectType, object }, {client, service}, emit) {
204
- const tableName = modelRuntime().tableName
205
- const prefix = JSON.stringify(objectType) + ':' + JSON.stringify(object)
206
- const promises = otherPropertyNames.map(async (propertyName) => {
207
- const indexName = tableName + '_by' + propertyName[0].toUpperCase() + propertyName.slice(1)
208
- const bucketSize = 32
209
- let found = false
210
- let bucket
211
- do {
212
- bucket = await app.dao.get(['database', 'indexRange', app.databaseName, indexName, {
213
- gte: prefix + ':',
214
- lte: prefix + '_\xFF\xFF\xFF\xFF',
215
- limit: bucketSize
216
- }])
217
- if(bucket.length > 0) found = true
218
- const deleteTriggerPromises = bucket.map(({to}) => [
219
- service.trigger({
220
- type: 'delete'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
221
- objectType: service.name+'_'+modelName,
222
- object: to
223
- }),
224
- service.trigger({
225
- type: 'deleteObject',
226
- objectType: service.name+'_'+modelName,
227
- object: to
228
- })
229
- ]).flat()
230
- await Promise.all(deleteTriggerPromises)
231
- } while (bucket.length == bucketSize)
232
- if(found) {
233
- const eventName = propertyName + reverseRelationWord + modelName + 'DeleteByOwner'
234
- emit({
235
- type: eventName,
236
- ownerType: objectType,
237
- owner: object
238
- })
239
- }
240
- })
241
- await Promise.all(promises)
242
- }
243
- }))
192
+ registerParentDeleteTriggers(context, config)
244
193
  }
245
194
 
246
195
  module.exports = {