@live-change/relations-plugin 0.7.33 → 0.7.35

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,260 @@
1
+ const { extractObjectData, extractIdentifiers } = require("./dataUtils.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, app } = context
9
+ const changeType = data ? (oldData ? 'update' : 'create') : 'delete'
10
+ await Promise.all([
11
+ app.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
+ app.trigger({
20
+ type: changeType+'Object',
21
+ objectType,
22
+ object,
23
+ identifiers,
24
+ data,
25
+ oldData
26
+ })
27
+ ])
28
+ }
29
+
30
+ async function iterateChildren(context, propertyName, path, cb) {
31
+ const {
32
+ service, modelRuntime, objectType: myType, writeableProperties, modelName,
33
+ reverseRelationWord, app, otherPropertyNames, sameIdAsParent
34
+ } = context
35
+ if(sameIdAsParent) {
36
+ const entity = await modelRuntime().get(path)
37
+ if(entity) await cb(entity)
38
+ } else {
39
+ const indexName = 'by' + propertyName[0].toUpperCase() + propertyName.slice(1)
40
+ const bucketSize = 32
41
+ let bucket
42
+ let gt = ''
43
+ do {
44
+ bucket = await modelRuntime().sortedIndexRangeGet(indexName, path, {
45
+ gt,
46
+ limit: bucketSize
47
+ })
48
+ //console.log("BUCKET", bucket)
49
+ if(bucket.length == 0) break
50
+ gt = bucket[bucket.length - 1].id
51
+ const copyTriggerPromises = bucket.map(entity => cb({ ...entity, id: entity.to }))
52
+ await Promise.all(copyTriggerPromises)
53
+ } while (bucket.length == bucketSize)
54
+ }
55
+ }
56
+
57
+
58
+ async function triggerDeleteOnParentDeleteTriggers(
59
+ context, propertyName, path, objectType, object, emit) {
60
+ const {
61
+ service, modelRuntime, objectType: myType, writeableProperties, modelName,
62
+ reverseRelationWord, otherPropertyNames
63
+ } = context
64
+
65
+ let found = false
66
+ await iterateChildren(context, propertyName, path, async entity => {
67
+ found = true
68
+ const identifiers = extractIdentifiers(otherPropertyNames, entity)
69
+ await fireChangeTriggers(context, myType, identifiers, entity.id,
70
+ extractObjectData(writeableProperties, entity, {}), null)
71
+ })
72
+ if (found) {
73
+ const eventName = propertyName + reverseRelationWord + modelName + 'DeleteByOwner'
74
+ emit({
75
+ type: eventName,
76
+ ownerType: objectType,
77
+ owner: object
78
+ })
79
+ }
80
+ }
81
+
82
+ function registerParentDeleteTriggers(context, config) {
83
+ const {
84
+ service, parentsTypes, otherPropertyNames,
85
+ } = context
86
+ if(parentsTypes) {
87
+ for (const index in parentsTypes) {
88
+ const otherType = parentsTypes[index]
89
+ const propertyName = otherPropertyNames[index]
90
+ const triggerName = 'delete' + otherType[0].toUpperCase() + otherType.slice(1)
91
+ if (!service.triggers[triggerName]) service.triggers[triggerName] = []
92
+ service.triggers[triggerName].push(new TriggerDefinition({
93
+ name: triggerName,
94
+ properties: {
95
+ object: {
96
+ type: String
97
+ }
98
+ },
99
+ async execute({object}, {client, service}, emit) {
100
+ await triggerDeleteOnParentDeleteTriggers(context, propertyName, [object],
101
+ otherType, object, emit)
102
+ }
103
+ }))
104
+ }
105
+ } else {
106
+ const triggerName = 'deleteObject'
107
+ if(!service.triggers[triggerName]) service.triggers[triggerName] = []
108
+ service.triggers[triggerName].push(new TriggerDefinition({
109
+ name: triggerName,
110
+ properties: {
111
+ objectType: {
112
+ type: String,
113
+ },
114
+ object: {
115
+ type: String
116
+ }
117
+ },
118
+ async execute({ objectType, object }, {client, service}, emit) {
119
+ for(const propertyName of otherPropertyNames) {
120
+ await triggerDeleteOnParentDeleteTriggers(context, propertyName, [objectType, object],
121
+ objectType, object, emit)
122
+ }
123
+ }
124
+ }))
125
+ }
126
+ }
127
+
128
+ async function copyObject(context, objectType, object, parentType, parent, identifiers, data, emit) {
129
+ const {
130
+ app, service, modelPropertyName, modelName, otherPropertyNames, joinedOthersPropertyName, others
131
+ } = context
132
+ const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Copied'
133
+ const newIdentifiers = {
134
+ ...identifiers
135
+ }
136
+ for(let i = 0; i < others.length; i++) {
137
+ const other = others[i]
138
+ if(other == parentType) {
139
+ newIdentifiers[otherPropertyNames[i]] = parent
140
+ }
141
+ }
142
+ console.log("COPY OBJECT", objectType, object, "TO", parentType, parent)
143
+ console.log("IDENTIFIERS", newIdentifiers)
144
+ console.log("DATA", data)
145
+
146
+ const newId = app.generateUid()
147
+ app.trigger({
148
+ type: 'copy'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
149
+ objectType,
150
+ object: newId,
151
+ from: object,
152
+ identifiers: newIdentifiers,
153
+ data
154
+ })
155
+ app.trigger({
156
+ type: 'copyObject',
157
+ objectType,
158
+ object: newId,
159
+ from: object,
160
+ identifiers: newIdentifiers,
161
+ data
162
+ })
163
+ await fireChangeTriggers(context, objectType, newIdentifiers, newId, null, data)
164
+ emit({
165
+ type: eventName,
166
+ [modelPropertyName]: newId,
167
+ ['from'+modelPropertyName[0].toUpperCase() + modelPropertyName.slice(1)]: object,
168
+ identifiers: newIdentifiers,
169
+ data
170
+ })
171
+ }
172
+
173
+ async function triggerCopyOnParentCopyTriggers(
174
+ context, propertyName, path, objectType, object, from, emit) {
175
+ const {
176
+ service, modelRuntime, objectType: myType, writeableProperties, modelName,
177
+ reverseRelationWord, app, otherPropertyNames
178
+ } = context
179
+ await iterateChildren(context, propertyName, path, async entity => {
180
+ const data = extractObjectData(writeableProperties, entity, {})
181
+ const identifiers = extractIdentifiers(otherPropertyNames, entity)
182
+ const fromId = entity.id
183
+
184
+ console.log("TRIGGERED COPY", myType, fromId, "FROM", objectType, from, "TO", object)
185
+
186
+ //console.log("COPY TRIGGER", myType, fromId, objectType, object, from, identifiers, data)
187
+ const copyTriggerResults = await app.trigger({
188
+ type: 'copyOnParentCopy'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
189
+ objectType: myType,
190
+ object: fromId,
191
+ parentType: objectType,
192
+ parent: object,
193
+ fromParent: from,
194
+ identifiers,
195
+ data
196
+ })
197
+ //console.log("COPY TRIGGER RESULTS", copyTriggerResults)
198
+ if(copyTriggerResults.length == 0) { // normal copy, without special logic
199
+ await copyObject(context, myType, fromId, objectType, object, identifiers, data, emit)
200
+ }
201
+ })
202
+ }
203
+
204
+ function registerParentCopyTriggers(context, config) {
205
+ const {
206
+ service, parentsTypes, otherPropertyNames, modelName
207
+ } = context
208
+ if(parentsTypes) {
209
+ for (const index in parentsTypes) {
210
+ const otherType = parentsTypes[index]
211
+ const propertyName = otherPropertyNames[index]
212
+ const triggerName = 'copy' + otherType[0].toUpperCase() + otherType.slice(1)
213
+ if (!service.triggers[triggerName]) service.triggers[triggerName] = []
214
+ service.triggers[triggerName].push(new TriggerDefinition({
215
+ name: triggerName,
216
+ properties: {
217
+ object: {
218
+ type: String
219
+ },
220
+ from: {
221
+ type: String
222
+ }
223
+ },
224
+ async execute({ object , from }, {client, service}, emit) {
225
+ await triggerCopyOnParentCopyTriggers(context, propertyName, [from],
226
+ otherType, object, from, emit)
227
+ }
228
+ }))
229
+ }
230
+ } else {
231
+ const triggerName = 'copyObject'
232
+ if(!service.triggers[triggerName]) service.triggers[triggerName] = []
233
+ service.triggers[triggerName].push(new TriggerDefinition({
234
+ name: triggerName,
235
+ properties: {
236
+ objectType: {
237
+ type: String,
238
+ },
239
+ object: {
240
+ type: String
241
+ },
242
+ from: {
243
+ type: String
244
+ }
245
+ },
246
+ async execute({ objectType, object, from }, {client, service}, emit) {
247
+ for(const propertyName of otherPropertyNames) {
248
+ await triggerCopyOnParentCopyTriggers(context, propertyName, [objectType, from],
249
+ objectType, object, from, emit)
250
+ }
251
+ }
252
+ }))
253
+ }
254
+ }
255
+
256
+ module.exports = {
257
+ fireChangeTriggers,
258
+ registerParentDeleteTriggers,
259
+ registerParentCopyTriggers,
260
+ }
package/dataUtils.js ADDED
@@ -0,0 +1,24 @@
1
+ const App = require("@live-change/framework");
2
+
3
+ function extractIdentifiers(otherPropertyNames, properties) {
4
+ const identifiers = {}
5
+ for (const propertyName of otherPropertyNames) {
6
+ identifiers[propertyName] = properties[propertyName]
7
+ }
8
+ return identifiers
9
+ }
10
+
11
+ function extractObjectData(writeableProperties, properties, defaults) {
12
+ let objectData = {}
13
+ for (const propertyName of writeableProperties) {
14
+ if (properties.hasOwnProperty(propertyName)) {
15
+ objectData[propertyName] = properties[propertyName]
16
+ }
17
+ }
18
+ return App.utils.mergeDeep({}, defaults, JSON.parse(JSON.stringify(objectData)))
19
+ }
20
+
21
+ module.exports = {
22
+ extractIdentifiers,
23
+ extractObjectData
24
+ }
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/itemEvents.js CHANGED
@@ -57,4 +57,22 @@ function defineDeletedEvent(config, context) {
57
57
  })
58
58
  }
59
59
 
60
- module.exports = { defineCreatedEvent, defineUpdatedEvent, defineTransferredEvent, defineDeletedEvent }
60
+ function defineCopyEvent(config, context) {
61
+ const {
62
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName, reverseRelationWord
63
+ } = context
64
+ const eventName = joinedOthersPropertyName + reverseRelationWord + modelName + 'Copied'
65
+ service.events[eventName] = new EventDefinition({
66
+ name: eventName,
67
+ execute(properties) {
68
+ const id = properties[modelPropertyName]
69
+ console.log("COPY CREATE", { ...properties.data, ...properties.identifiers, id })
70
+ return modelRuntime().create({ ...properties.data, ...properties.identifiers, id })
71
+ }
72
+ })
73
+ }
74
+
75
+ module.exports = {
76
+ defineCreatedEvent, defineUpdatedEvent, defineTransferredEvent, defineDeletedEvent,
77
+ defineCopyEvent,
78
+ }
package/itemOf.js CHANGED
@@ -1,15 +1,17 @@
1
1
  const {
2
2
  defineProperties, defineIndexes,
3
3
  processModelsAnnotation, addAccessControlParents,
4
- defineDeleteByOwnerEvents, defineParentDeleteTriggers
4
+ defineDeleteByOwnerEvents, defineParentDeleteTriggers, defineParentCopyTriggers
5
5
  } = require('./utils.js')
6
6
 
7
7
  const {
8
8
  defineCreatedEvent, defineUpdatedEvent, defineDeletedEvent, defineTransferredEvent,
9
+ defineCopyEvent
9
10
  } = require('./itemEvents.js')
10
11
 
11
12
  const {
12
- defineView, defineCreateAction, defineUpdateAction, defineDeleteAction, defineSortIndex
13
+ defineView, defineCreateAction, defineUpdateAction, defineDeleteAction, defineSortIndex,
14
+ defineCopyAction, defineCopyOnParentCopyTrigger
13
15
  } = require('./pluralRelationUtils.js')
14
16
 
15
17
  module.exports = function(service, app) {
@@ -38,6 +40,7 @@ module.exports = function(service, app) {
38
40
  defineTransferredEvent(config, context)
39
41
  defineDeletedEvent(config, context)
40
42
  defineDeleteByOwnerEvents(config, context)
43
+ defineCopyEvent(config, context)
41
44
 
42
45
  if(config.createAccess || config.writeAccess || config.createAccessControl || config.writeAccessControl) {
43
46
  defineCreateAction(config, context)
@@ -51,6 +54,18 @@ module.exports = function(service, app) {
51
54
  defineDeleteAction(config, context)
52
55
  }
53
56
 
54
- if(!config.customDeleteTrigger) defineParentDeleteTriggers(config, context)
57
+ if(config.copyAccess || config.copyAccessControl) {
58
+ defineCopyAction(config, context)
59
+ }
60
+
61
+ if(!config.customDeleteTrigger) {
62
+ defineParentDeleteTriggers(config, context)
63
+ }
64
+
65
+ if(!config.customParentCopyTrigger) {
66
+ defineParentCopyTriggers(config, context)
67
+ //defineCopyOnParentCopyTrigger(config, context)
68
+ }
69
+
55
70
  })
56
71
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/relations-plugin",
3
- "version": "0.7.33",
3
+ "version": "0.7.35",
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.33",
24
+ "@live-change/framework": "^0.7.35",
25
25
  "pluralize": "^8.0.0"
26
26
  },
27
- "gitHead": "244a5a0eccac3b8fe8f9efc0d8cca08f4e383b60"
27
+ "gitHead": "11313d136ef6bc6770050671a61721c2fa7586f9"
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
@@ -1,8 +1,9 @@
1
1
  const App = require("@live-change/framework")
2
- const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition } = App
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, TriggerDefinition } = App
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
@@ -172,6 +177,156 @@ function defineDeleteAction(config, context) {
172
177
  })
173
178
  }
174
179
 
180
+ function defineCopyAction(config, context) {
181
+ const {
182
+ service, app, model, modelRuntime, modelPropertyName, objectType,
183
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others,
184
+ identifiers
185
+ } = context
186
+ const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Copied'
187
+ const actionName = 'copy' + joinedOthersClassName + context.reverseRelationWord + modelName
188
+ const accessControl = config.copyAccessControl
189
+ prepareAccessControl(accessControl, otherPropertyNames, others)
190
+ service.actions[actionName] = new ActionDefinition({
191
+ name: actionName,
192
+ properties: {
193
+ [modelPropertyName]: {
194
+ type: model,
195
+ validation: ['nonEmpty']
196
+ },
197
+ ...(identifiers),
198
+ updates: {
199
+ type: 'object',
200
+ properties: {
201
+ ...(model.properties)
202
+ }
203
+ }
204
+ },
205
+ access: config.copyAccess,
206
+ skipValidation: true,
207
+ //queuedBy: otherPropertyNames,
208
+ waitForEvents: true,
209
+ async execute(properties, { client, service }, emit) {
210
+ const id = properties[modelPropertyName]
211
+ const entity = await modelRuntime().get(id)
212
+ if(!entity) throw new Error('not_found')
213
+ const entityIdParts = extractIdParts(otherPropertyNames, entity)
214
+ const idParts = extractIdParts(otherPropertyNames, properties)
215
+ const identifiers = extractIdentifiers(otherPropertyNames, entity)
216
+ if(JSON.stringify(entityIdParts) != JSON.stringify(idParts)) {
217
+ throw new Error('not_authorized')
218
+ }
219
+ const srcData = extractObjectData(writeableProperties, properties, entity)
220
+ const updatedData = App.utils.mergeDeep(srcData, properties.updates)
221
+ const newId = app.generateUid()
222
+ const dataWithIdentifiers = { [modelPropertyName]: newId, ...identifiers, ...updatedData }
223
+ await App.validation.validate(dataWithIdentifiers, validators,
224
+ { source: action, action, service, app, client })
225
+ app.trigger({
226
+ type: 'copy'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
227
+ objectType,
228
+ object: newId,
229
+ from: id,
230
+ identifiers,
231
+ data: updatedData
232
+ }),
233
+ app.trigger({
234
+ type: 'copyObject',
235
+ objectType,
236
+ object: newId,
237
+ from: id,
238
+ identifiers,
239
+ data: updatedData
240
+ })
241
+ await fireChangeTriggers(context, objectType, identifiers, newId, null, updatedData)
242
+ emit({
243
+ type: eventName,
244
+ [modelPropertyName]: newId,
245
+ ['from'+modelPropertyName[0].toUpperCase() + modelPropertyName.slice(1)]: id,
246
+ identifiers,
247
+ data: updatedData
248
+ })
249
+ return {
250
+ newId,
251
+ }
252
+ }
253
+ })
254
+ const action = service.actions[actionName]
255
+ const validators = App.validation.getValidators(action, service, action)
256
+ }
257
+
258
+ function defineCopyOnParentCopyTrigger(config, context) {
259
+ const {
260
+ service, app, model, modelRuntime, modelPropertyName, objectType,
261
+ otherPropertyNames, others, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName,
262
+ } = context
263
+ const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Copied'
264
+ const triggerName = 'copyOnParentCopy_' + service.name + '_' + modelName
265
+ if(!service.triggers[triggerName]) service.triggers[triggerName] = []
266
+ service.triggers[triggerName].push(new TriggerDefinition({
267
+ name: triggerName,
268
+ properties: {
269
+ objectType: {
270
+ type: String,
271
+ },
272
+ object: {
273
+ type: String,
274
+ },
275
+ parentType: {
276
+ type: String,
277
+ },
278
+ parent: {
279
+ type: String,
280
+ },
281
+ fromParent: {
282
+ type: String,
283
+ },
284
+ identifiers: {
285
+ type: Object,
286
+ },
287
+ data: {
288
+ type: Object,
289
+ }
290
+ },
291
+ async execute({ objectType, object, parentType, parent, fromParent, identifiers, data }, {client, service}, emit) {
292
+ const newIdentifiers = {
293
+ ...identifiers
294
+ }
295
+ for(let i = 0; i < others.length; i++) {
296
+ const other = others[i]
297
+ if(other == parentType) {
298
+ newIdentifiers[otherPropertyNames[i]] = parent
299
+ }
300
+ }
301
+ const newId = app.generateUid()
302
+ app.trigger({
303
+ type: 'copy'+service.name[0].toUpperCase()+service.name.slice(1)+'_'+modelName,
304
+ objectType,
305
+ object: newId,
306
+ from: object,
307
+ identifiers: newIdentifiers,
308
+ data
309
+ })
310
+ app.trigger({
311
+ type: 'copyObject',
312
+ objectType,
313
+ object: newId,
314
+ from: object,
315
+ identifiers: newIdentifiers,
316
+ data
317
+ })
318
+ await fireChangeTriggers(context, objectType, newIdentifiers, newId, null, data)
319
+ emit({
320
+ type: eventName,
321
+ [modelPropertyName]: newId,
322
+ ['from'+modelPropertyName[0].toUpperCase() + modelPropertyName.slice(1)]: object,
323
+ identifiers,
324
+ data
325
+ })
326
+ }
327
+ }))
328
+ }
329
+
175
330
  function defineSortIndex(context, sortFields) {
176
331
  if(!Array.isArray(sortFields)) sortFields = [sortFields]
177
332
  console.log("DEFINE SORT INDEX", sortFields)
@@ -182,4 +337,9 @@ function defineSortIndex(context, sortFields) {
182
337
  })
183
338
  }
184
339
 
185
- module.exports = { defineView, defineCreateAction, defineUpdateAction, defineDeleteAction, defineSortIndex }
340
+ module.exports = {
341
+ defineView,
342
+ defineCreateAction, defineUpdateAction, defineDeleteAction, defineCopyAction,
343
+ defineCopyOnParentCopyTrigger,
344
+ defineSortIndex,
345
+ }
package/propertyOf.js CHANGED
@@ -16,6 +16,8 @@ module.exports = function(service, app) {
16
16
  context.relationWord = 'Property'
17
17
  context.reverseRelationWord = 'Owned'
18
18
 
19
+ context.sameIdAsParent = true
20
+
19
21
  context.identifiers = defineProperties(context.model, context.others, context.otherPropertyNames)
20
22
  addAccessControlParents(context)
21
23
  defineIndexes(context.model, context.otherPropertyNames, context.others)
package/propertyOfAny.js CHANGED
@@ -20,6 +20,8 @@ module.exports = function(service, app) {
20
20
  context.reverseRelationWord = 'Owned'
21
21
  context.partialReverseRelationWord = 'Owned'
22
22
 
23
+ context.sameIdAsParent = true
24
+
23
25
  context.identifiers = defineAnyProperties(context.model, context.otherPropertyNames)
24
26
  addAccessControlAnyParents(context)
25
27
  defineAnyIndexes(context.model, context.otherPropertyNames, false)
@@ -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,10 +1,17 @@
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 {
5
+ fireChangeTriggers, registerParentDeleteTriggers, registerParentCopyTriggers
6
+ } = require("./changeTriggers.js")
4
7
  const {
5
8
  PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition, TriggerDefinition
6
9
  } = App
7
10
 
11
+ const {
12
+ extractObjectData, extractIdentifiers
13
+ } = require('./dataUtils.js')
14
+
8
15
  function extractIdParts(otherPropertyNames, properties) {
9
16
  const idParts = []
10
17
  for (const propertyName of otherPropertyNames) {
@@ -13,13 +20,6 @@ function extractIdParts(otherPropertyNames, properties) {
13
20
  return idParts
14
21
  }
15
22
 
16
- function extractIdentifiers(otherPropertyNames, properties) {
17
- const identifiers = {}
18
- for (const propertyName of otherPropertyNames) {
19
- identifiers[propertyName] = properties[propertyName]
20
- }
21
- return identifiers
22
- }
23
23
 
24
24
  function generateId(otherPropertyNames, properties) {
25
25
  return otherPropertyNames.length > 1
@@ -27,16 +27,6 @@ function generateId(otherPropertyNames, properties) {
27
27
  : properties[otherPropertyNames[0]]
28
28
  }
29
29
 
30
- function extractObjectData(writeableProperties, properties, defaults) {
31
- let objectData = {}
32
- for (const propertyName of writeableProperties) {
33
- if (properties.hasOwnProperty(propertyName)) {
34
- objectData[propertyName] = properties[propertyName]
35
- }
36
- }
37
- return App.utils.mergeDeep({}, defaults, JSON.parse(JSON.stringify(objectData)))
38
- }
39
-
40
30
  function defineProperties(model, types, names) {
41
31
  const identifiers = {}
42
32
  for (let i = 0; i < types.length; i++) {
@@ -113,16 +103,18 @@ function processModelsAnnotation(service, app, annotation, multiple, cb) {
113
103
  const others = what.map(other => other.getTypeName ? other.getTypeName() : (other.name ? other.name : other))
114
104
 
115
105
  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')
106
+ const otherNames = what.map(other => other.name ? other.name : other)
107
+ const otherPropertyNames = otherNames.map(name => name[0].toLowerCase() + name.slice(1))
108
+
109
+ const joinedOthersPropertyName = (otherNames[0][0].toLowerCase() + otherNames[0].slice(1)) +
110
+ (otherNames.length > 1 ? ('And' + otherNames.slice(1).join('And')) : '')
111
+ const joinedOthersClassName = otherNames.join('And')
112
+ const objectType = service.name + '_' + modelName
121
113
 
122
114
  const context = {
123
115
  service, app, model, originalModelProperties, modelProperties, modelPropertyName, defaults, modelRuntime,
124
116
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName,
125
- others, annotation
117
+ others, annotation, objectType, parentsTypes: others
126
118
  }
127
119
 
128
120
  cb(config, context)
@@ -188,66 +180,16 @@ function defineDeleteByOwnerEvents(config, context, generateId) {
188
180
  }
189
181
 
190
182
  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
- }
183
+ registerParentDeleteTriggers(context, config)
247
184
  }
248
185
 
186
+ function defineParentCopyTriggers(config, context) {
187
+ registerParentCopyTriggers(context, config)
188
+ }
189
+
190
+
249
191
  module.exports = {
250
192
  extractIdParts, extractIdentifiers, extractObjectData, defineProperties, defineIndex, defineIndexes,
251
193
  processModelsAnnotation, generateId, addAccessControlParents, prepareAccessControl,
252
- defineDeleteByOwnerEvents, defineParentDeleteTriggers
194
+ defineDeleteByOwnerEvents, defineParentDeleteTriggers, defineParentCopyTriggers,
253
195
  }
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("./dataUtils.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 = {