@live-change/relations-plugin 0.8.23 → 0.8.25

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.
@@ -1,7 +1,7 @@
1
1
  import App from "@live-change/framework"
2
2
  const { extractRange } = App
3
3
  import {
4
- PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition
4
+ PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, TriggerDefinition
5
5
  } from "@live-change/framework"
6
6
  import { extractTypeAndIdParts, extractIdentifiersWithTypes, prepareAccessControl } from "./utilsAny.js"
7
7
  import { extractObjectData, extractIdentifiers} from "./utils.js"
@@ -9,7 +9,7 @@ import { fireChangeTriggers } from "./changeTriggers.js"
9
9
 
10
10
  import pluralize from 'pluralize'
11
11
 
12
- function defineView(config, context) {
12
+ function defineView(config, context, external = true) {
13
13
  const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
14
14
  modelName, others, model } = context
15
15
  const indexName = 'by'+context.joinedOthersClassName
@@ -24,7 +24,7 @@ function defineView(config, context) {
24
24
  validation: ['nonEmpty']
25
25
  })
26
26
  }
27
- const accessControl = config.readAccessControl || config.writeAccessControl
27
+ const accessControl = external && (config.readAccessControl || config.writeAccessControl)
28
28
  prepareAccessControl(accessControl, otherPropertyNames)
29
29
  const viewName = joinedOthersPropertyName + context.reverseRelationWord + pluralize(modelName)
30
30
  service.views[viewName] = new ViewDefinition({
@@ -39,7 +39,8 @@ function defineView(config, context) {
39
39
  type: model
40
40
  }
41
41
  },
42
- access: config.readAccess || config.writeAccess,
42
+ internal: !external,
43
+ access: external && (config.readAccess || config.writeAccess),
43
44
  accessControl,
44
45
  daoPath(properties, { client, context }) {
45
46
  const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
@@ -50,16 +51,40 @@ function defineView(config, context) {
50
51
  })
51
52
  }
52
53
 
53
- function defineCreateAction(config, context) {
54
+ function getCreateFunction( validators, validationContext, config, context) {
54
55
  const {
55
56
  service, app, model, modelPropertyName, modelRuntime, objectType,
56
57
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
57
58
  } = context
58
59
  const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Created'
60
+ return async function execute(properties, { client, service }, emit) {
61
+ const id = properties[modelPropertyName] || app.generateUid()
62
+ const entity = await modelRuntime().get(id)
63
+ if(entity) throw 'exists'
64
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
65
+ const data = extractObjectData(writeableProperties, properties,
66
+ App.computeDefaults(model, properties, { client, service } ))
67
+ await App.validation.validate({ ...identifiers, ...data }, validators,
68
+ validationContext)
69
+ await fireChangeTriggers(context, objectType, identifiers, id, null, data)
70
+ emit({
71
+ type: eventName,
72
+ [modelPropertyName]: id,
73
+ identifiers, data
74
+ })
75
+ return id
76
+ }
77
+ }
78
+
79
+ function defineCreateAction(config, context) {
80
+ const {
81
+ service, app, model, modelPropertyName, modelRuntime, objectType,
82
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
83
+ } = context
59
84
  const actionName = 'create' + joinedOthersClassName + context.reverseRelationWord + modelName
60
85
  const accessControl = config.createAccessControl || config.writeAccessControl
61
86
  prepareAccessControl(accessControl, otherPropertyNames)
62
- service.actions[actionName] = new ActionDefinition({
87
+ const action = new ActionDefinition({
63
88
  name: actionName,
64
89
  properties: {
65
90
  ...(model.properties)
@@ -69,26 +94,71 @@ function defineCreateAction(config, context) {
69
94
  skipValidation: true,
70
95
  //queuedBy: otherPropertyNames,
71
96
  waitForEvents: true,
72
- async execute(properties, { client, service }, emit) {
73
- const id = properties[modelPropertyName] || app.generateUid()
74
- const entity = await modelRuntime().get(id)
75
- if(entity) throw 'exists'
76
- const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
77
- const data = extractObjectData(writeableProperties, properties,
78
- App.computeDefaults(model, properties, { client, service } ))
79
- await App.validation.validate({ ...identifiers, ...data }, validators,
80
- { source: action, action, service, app, client })
81
- await fireChangeTriggers(context, objectType, identifiers, id, null, data)
82
- emit({
83
- type: eventName,
84
- [modelPropertyName]: id,
85
- identifiers, data
86
- })
87
- return id
88
- }
97
+ execute: () => { throw new Error('not generated yet') }
89
98
  })
90
- const action = service.actions[actionName]
91
99
  const validators = App.validation.getValidators(action, service, action)
100
+ const validationContext = { source: action, action }
101
+ action.execute = getCreateFunction( validators, validationContext, config, context)
102
+ service.actions[actionName] = action
103
+ }
104
+
105
+ function defineCreateTrigger(config, context) {
106
+ const {
107
+ service, app, model, modelPropertyName, modelRuntime, objectType,
108
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
109
+ } = context
110
+ const actionName = 'create' + joinedOthersClassName + context.reverseRelationWord + modelName
111
+ const triggerName = `${service.name}_${actionName}`
112
+ const trigger = new TriggerDefinition({
113
+ name: triggerName,
114
+ properties: {
115
+ ...(model.properties)
116
+ },
117
+ access: config.createAccess || config.writeAccess,
118
+ skipValidation: true,
119
+ //queuedBy: otherPropertyNames,
120
+ waitForEvents: true,
121
+ execute: () => { throw new Error('not generated yet') }
122
+ })
123
+ const validators = App.validation.getValidators(trigger, service, trigger)
124
+ const validationContext = { source: trigger, trigger }
125
+ trigger.execute = getCreateFunction( validators, validationContext, config, context)
126
+ service.triggers[triggerName] = [trigger]
127
+ }
128
+
129
+ function getUpdateFunction( validators, validationContext, config, context) {
130
+ const {
131
+ service, app, model, modelPropertyName, modelRuntime, objectType,
132
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
133
+ } = context
134
+ const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
135
+ return async function execute(properties, { client, service }, emit) {
136
+ const id = properties[modelPropertyName]
137
+ if(!id) throw 'no_id'
138
+ const entity = await modelRuntime().get(id)
139
+ if(!entity) throw 'not_found'
140
+ const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
141
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
142
+ if(JSON.stringify(entityTypeAndIdParts) !== JSON.stringify(typeAndIdParts)) {
143
+ throw 'not_authorized'
144
+ }
145
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
146
+ const data = App.utils.mergeDeep({},
147
+ extractObjectData(writeableProperties, properties, entity),
148
+ App.computeUpdates(model, { ...entity, ...properties }, { client, service })
149
+ )
150
+ await App.validation.validate({ ...identifiers, ...data }, validators,
151
+ validationContext)
152
+ await fireChangeTriggers(context, objectType, identifiers, id,
153
+ extractObjectData(writeableProperties, entity, {}), data)
154
+ emit({
155
+ type: eventName,
156
+ [modelPropertyName]: id,
157
+ identifiers,
158
+ data
159
+ })
160
+ }
161
+
92
162
  }
93
163
 
94
164
  function defineUpdateAction(config, context) {
@@ -96,11 +166,10 @@ function defineUpdateAction(config, context) {
96
166
  service, app, model, modelRuntime, modelPropertyName, objectType,
97
167
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
98
168
  } = context
99
- const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Updated'
100
169
  const actionName = 'update' + joinedOthersClassName + context.reverseRelationWord + modelName
101
170
  const accessControl = config.updateAccessControl || config.writeAccessControl
102
171
  prepareAccessControl(accessControl, otherPropertyNames)
103
- service.actions[actionName] = new ActionDefinition({
172
+ const action = new ActionDefinition({
104
173
  name: actionName,
105
174
  properties: {
106
175
  [modelPropertyName]: {
@@ -114,32 +183,64 @@ function defineUpdateAction(config, context) {
114
183
  skipValidation: true,
115
184
  //queuedBy: otherPropertyNames,
116
185
  waitForEvents: true,
117
- async execute(properties, { client, service }, emit) {
118
- const id = properties[modelPropertyName]
119
- if(!id) throw 'no_id'
120
- const entity = await modelRuntime().get(id)
121
- if(!entity) throw 'not_found'
122
- const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
123
- const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
124
- if(JSON.stringify(entityTypeAndIdParts) !== JSON.stringify(typeAndIdParts)) {
125
- throw 'not_authorized'
126
- }
127
- const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
128
- const data = extractObjectData(writeableProperties, properties, entity)
129
- await App.validation.validate({ ...identifiers, ...data }, validators,
130
- { source: action, action, service, app, client })
131
- await fireChangeTriggers(context, objectType, identifiers, id,
132
- extractObjectData(writeableProperties, entity, {}), data)
133
- emit({
134
- type: eventName,
135
- [modelPropertyName]: id,
136
- identifiers,
137
- data
138
- })
139
- }
186
+ execute: () => { throw new Error('not generated yet') }
140
187
  })
141
- const action = service.actions[actionName]
142
188
  const validators = App.validation.getValidators(action, service, action)
189
+ const validationContext = { source: action, action }
190
+ action.execute = getUpdateFunction( validators, validationContext, config, context)
191
+ service.actions[actionName] = action
192
+ }
193
+
194
+ function defineUpdateTrigger(config, context) {
195
+ const {
196
+ service, app, model, modelRuntime, modelPropertyName, objectType,
197
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
198
+ } = context
199
+ const actionName = 'update' + joinedOthersClassName + context.reverseRelationWord + modelName
200
+ const triggerName = `${service.name}_${actionName}`
201
+ const trigger = new TriggerDefinition({
202
+ name: triggerName,
203
+ properties: {
204
+ [modelPropertyName]: {
205
+ type: model,
206
+ validation: ['nonEmpty']
207
+ },
208
+ ...(model.properties)
209
+ },
210
+ access: config.updateAccess || config.writeAccess,
211
+ skipValidation: true,
212
+ //queuedBy: otherPropertyNames,
213
+ waitForEvents: true,
214
+ execute: () => { throw new Error('not generated yet') }
215
+ })
216
+ const validators = App.validation.getValidators(trigger, service, trigger)
217
+ const validationContext = { source: trigger, trigger }
218
+ trigger.execute = getUpdateFunction( validators, validationContext, config, context)
219
+ service.triggers[triggerName] = [trigger]
220
+ }
221
+
222
+ function getDeleteFunction(config, context) {
223
+ const {
224
+ service, app, model, modelPropertyName, modelRuntime, objectType,
225
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
226
+ } = context
227
+ const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Deleted'
228
+ return async function execute(properties, { client, service }, emit) {
229
+ const id = properties[modelPropertyName]
230
+ const entity = await modelRuntime().get(id)
231
+ if(!entity) throw 'not_found'
232
+ const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
233
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
234
+ if(JSON.stringify(entityTypeAndIdParts) !== JSON.stringify(typeAndIdParts)) {
235
+ throw 'not_authorized'
236
+ }
237
+ await fireChangeTriggers(context, objectType, extractIdentifiers(otherPropertyNames, entity), id,
238
+ extractObjectData(writeableProperties, entity, {}), null)
239
+ emit({
240
+ type: eventName,
241
+ [modelPropertyName]: id
242
+ })
243
+ }
143
244
  }
144
245
 
145
246
  function defineDeleteAction(config, context) {
@@ -147,11 +248,10 @@ function defineDeleteAction(config, context) {
147
248
  service, app, model, modelRuntime, modelPropertyName, identifiers, objectType,
148
249
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
149
250
  } = context
150
- const eventName = joinedOthersPropertyName + context.reverseRelationWord + modelName + 'Deleted'
151
251
  const actionName = 'delete' + joinedOthersClassName + context.reverseRelationWord + modelName
152
252
  const accessControl = config.deleteAccessControl || config.writeAccessControl
153
253
  prepareAccessControl(accessControl, otherPropertyNames)
154
- service.actions[actionName] = new ActionDefinition({
254
+ const action = new ActionDefinition({
155
255
  name: actionName,
156
256
  properties: {
157
257
  [modelPropertyName]: {
@@ -165,24 +265,36 @@ function defineDeleteAction(config, context) {
165
265
  skipValidation: true,
166
266
  //queuedBy: otherPropertyNames,
167
267
  waitForEvents: true,
168
- async execute(properties, { client, service }, emit) {
169
- const id = properties[modelPropertyName]
170
- const entity = await modelRuntime().get(id)
171
- if(!entity) throw new Error('not_found')
172
- const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
173
- const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
174
- const identifiers = extractIdentifiers(otherPropertyNames, entity)
175
- if(JSON.stringify(entityTypeAndIdParts) !== JSON.stringify(typeAndIdParts)) {
176
- throw new Error('not_authorized')
177
- }
178
- await fireChangeTriggers(context, objectType, identifiers, id,
179
- extractObjectData(writeableProperties, entity, {}), null)
180
- emit({
181
- type: eventName,
182
- [modelPropertyName]: id
183
- })
184
- }
268
+ execute: () => { throw new Error('not generated yet') }
185
269
  })
270
+ action.execute = getDeleteFunction(config, context)
271
+ service.actions[actionName] = action
272
+ }
273
+
274
+ function defineDeleteTrigger(config, context) {
275
+ const {
276
+ service, app, model, modelRuntime, modelPropertyName, identifiers, objectType,
277
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
278
+ } = context
279
+ const actionName = 'delete' + joinedOthersClassName + context.reverseRelationWord + modelName
280
+ const triggerName = `${service.name}_${actionName}`
281
+ const trigger = new TriggerDefinition({
282
+ name: triggerName,
283
+ properties: {
284
+ [modelPropertyName]: {
285
+ type: model,
286
+ validation: ['nonEmpty']
287
+ },
288
+ ...identifiers
289
+ },
290
+ access: config.deleteAccess || config.writeAccess,
291
+ skipValidation: true,
292
+ //queuedBy: otherPropertyNames,
293
+ waitForEvents: true,
294
+ execute: () => { throw new Error('not generated yet') }
295
+ })
296
+ trigger.execute = getDeleteFunction(config, context)
297
+ service.triggers[triggerName] = [trigger]
186
298
  }
187
299
 
188
300
  function defineSortIndex(context, sortFields) {
@@ -196,4 +308,9 @@ function defineSortIndex(context, sortFields) {
196
308
  })
197
309
  }
198
310
 
199
- export { defineView, defineCreateAction, defineUpdateAction, defineDeleteAction, defineSortIndex }
311
+ export {
312
+ defineView,
313
+ defineCreateAction, defineUpdateAction, defineDeleteAction,
314
+ defineCreateTrigger, defineUpdateTrigger, defineDeleteTrigger,
315
+ defineSortIndex
316
+ }