@live-change/relations-plugin 0.1.12 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/itemEvents.js ADDED
@@ -0,0 +1,60 @@
1
+ const App = require("@live-change/framework")
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
+
4
+ function defineCreatedEvent(config, context) {
5
+ const {
6
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
7
+ } = context
8
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Created'
9
+ service.events[eventName] = new EventDefinition({
10
+ name: eventName,
11
+ execute(properties) {
12
+ const id = properties[modelPropertyName]
13
+ return modelRuntime().create({ ...properties.data, ...properties.identifiers, id })
14
+ }
15
+ })
16
+ }
17
+
18
+ function defineUpdatedEvent(config, context) {
19
+ const {
20
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
21
+ } = context
22
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
23
+ service.events[eventName] = new EventDefinition({
24
+ name: eventName,
25
+ execute(properties) {
26
+ const id = properties[modelPropertyName]
27
+ return modelRuntime().update(id, { ...properties.data, ...properties.identifiers, id })
28
+ }
29
+ })
30
+ }
31
+
32
+ function defineTransferredEvent(config, context) {
33
+ const {
34
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
35
+ } = context
36
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Transferred'
37
+ service.events[eventName] = new EventDefinition({
38
+ name: eventName,
39
+ execute(properties) {
40
+ const id = properties[modelPropertyName]
41
+ return modelRuntime().update(id, { ...properties.to, id })
42
+ }
43
+ })
44
+ }
45
+
46
+ function defineDeletedEvent(config, context) {
47
+ const {
48
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
49
+ } = context
50
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Deleted'
51
+ service.events[eventName] = new EventDefinition({
52
+ name: eventName,
53
+ execute(properties) {
54
+ const id = properties[modelPropertyName]
55
+ return modelRuntime().delete(id)
56
+ }
57
+ })
58
+ }
59
+
60
+ module.exports = { defineCreatedEvent, defineUpdatedEvent, defineTransferredEvent, defineDeletedEvent }
package/itemOf.js CHANGED
@@ -40,19 +40,10 @@ function defineView(config, context) {
40
40
  })
41
41
  }
42
42
 
43
- async function defineCreatedEvent(config, context) {
44
- const {
45
- service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
46
- } = context
47
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Created'
48
- service.events[eventName] = new EventDefinition({
49
- name: eventName,
50
- execute(properties) {
51
- const id = properties[modelPropertyName]
52
- return modelRuntime().create({ ...properties.data, ...properties.identifiers, id })
53
- }
54
- })
55
- }
43
+ const {
44
+ defineCreatedEvent, defineUpdatedEvent, defineDeletedEvent, defineTransferredEvent,
45
+ } = require('./itemEvents.js')
46
+ const {defineTransferEvent} = require("./itemEvents");
56
47
 
57
48
  function defineCreateAction(config, context) {
58
49
  const {
@@ -88,21 +79,7 @@ function defineCreateAction(config, context) {
88
79
  const validators = App.validation.getValidators(action, service, action)
89
80
  }
90
81
 
91
- async function defineUpdatedEvent(config, context) {
92
- const {
93
- service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
94
- } = context
95
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
96
- service.events[eventName] = new EventDefinition({
97
- name: eventName,
98
- execute(properties) {
99
- const id = properties[modelPropertyName]
100
- return modelRuntime().update(id, { ...properties.data, ...properties.identifiers, id })
101
- }
102
- })
103
- }
104
-
105
- async function defineUpdateAction(config, context) {
82
+ function defineUpdateAction(config, context) {
106
83
  const {
107
84
  service, app, model, modelRuntime, modelPropertyName,
108
85
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
@@ -142,21 +119,7 @@ async function defineUpdateAction(config, context) {
142
119
  const validators = App.validation.getValidators(action, service, action)
143
120
  }
144
121
 
145
- async function defineDeletedEvent(config, context) {
146
- const {
147
- service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName
148
- } = context
149
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Deleted'
150
- service.events[eventName] = new EventDefinition({
151
- name: eventName,
152
- execute(properties) {
153
- const id = properties[modelPropertyName]
154
- return modelRuntime().delete(id)
155
- }
156
- })
157
- }
158
-
159
- async function defineDeleteAction(config, context) {
122
+ function defineDeleteAction(config, context) {
160
123
  const {
161
124
  service, app, model, modelRuntime, modelPropertyName,
162
125
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
@@ -218,6 +181,7 @@ module.exports = function(service, app) {
218
181
 
219
182
  defineCreatedEvent(config, context)
220
183
  defineUpdatedEvent(config, context)
184
+ defineTransferredEvent(config, context)
221
185
  defineDeletedEvent(config, context)
222
186
 
223
187
  if(config.setAccess || config.writeAccess) {
package/itemOfAny.js ADDED
@@ -0,0 +1,207 @@
1
+ const App = require("@live-change/framework")
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
+
4
+ const {
5
+ extractRange, extractObjectData
6
+ } = require('./utils.js')
7
+
8
+ const {
9
+ extractTypeAndIdParts, extractIdentifiersWithTypes, defineAnyProperties, defineAnyIndex,
10
+ processModelsAnyAnnotation
11
+ } = require('./utilsAny.js')
12
+
13
+ function defineView(config, context) {
14
+ const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
15
+ modelName, others, model } = context
16
+ const indexName = 'by'+context.joinedOthersClassName
17
+ const viewProperties = {}
18
+ for (let i = 0; i < others.length; i++) {
19
+ viewProperties[otherPropertyNames[i]] = new PropertyDefinition({
20
+ type: 'String',
21
+ validation: ['nonEmpty']
22
+ })
23
+ viewProperties[otherPropertyNames[i] + 'Type'] = new PropertyDefinition({
24
+ type: 'String',
25
+ validation: ['nonEmpty']
26
+ })
27
+ }
28
+ const viewName = joinedOthersPropertyName + 'Owned' + modelName + 's'
29
+ service.views[viewName] = new ViewDefinition({
30
+ name: viewName,
31
+ properties: {
32
+ ...viewProperties,
33
+ ...App.utils.rangeProperties
34
+ },
35
+ returns: {
36
+ type: Array,
37
+ of: {
38
+ type: model
39
+ }
40
+ },
41
+ access: config.readAccess,
42
+ daoPath(properties, { client, context }) {
43
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
44
+ const range = extractRange(properties)
45
+ const path = modelRuntime().sortedIndexRangePath(indexName, typeAndIdParts, range)
46
+ return path
47
+ }
48
+ })
49
+ }
50
+
51
+ const {
52
+ defineCreatedEvent, defineUpdatedEvent, defineDeletedEvent, defineTransferredEvent,
53
+ } = require('itemEvents.js')
54
+ const {defineTransferEvent} = require("./itemEvents");
55
+
56
+ function defineCreateAction(config, context) {
57
+ const {
58
+ service, app, model, defaults, modelPropertyName, modelRuntime,
59
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
60
+ } = context
61
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Created'
62
+ const actionName = 'set' + joinedOthersClassName + 'Owned' + modelName
63
+ service.actions[actionName] = new ActionDefinition({
64
+ name: actionName,
65
+ properties: {
66
+ ...(model.properties)
67
+ },
68
+ access: config.createAccess || config.writeAccess,
69
+ skipValidation: true,
70
+ //queuedBy: otherPropertyNames,
71
+ 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, defaults)
78
+ await App.validation.validate(data, validators, { source: action, action, service, app, client })
79
+ emit({
80
+ type: eventName,
81
+ [modelPropertyName]: id,
82
+ identifiers, data
83
+ })
84
+ }
85
+ })
86
+ const action = service.actions[actionName]
87
+ const validators = App.validation.getValidators(action, service, action)
88
+ }
89
+
90
+ function defineUpdateAction(config, context) {
91
+ const {
92
+ service, app, model, modelRuntime, modelPropertyName,
93
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
94
+ } = context
95
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
96
+ const actionName = 'update' + joinedOthersClassName + 'Owned' + modelName
97
+ service.actions[actionName] = new ActionDefinition({
98
+ name: actionName,
99
+ properties: {
100
+ ...(model.properties)
101
+ },
102
+ access: config.updateAccess || config.writeAccess,
103
+ skipValidation: true,
104
+ //queuedBy: otherPropertyNames,
105
+ waitForEvents: true,
106
+ async execute(properties, { client, service }, emit) {
107
+ const id = properties[modelPropertyName]
108
+ const entity = await modelRuntime().get(id)
109
+ if(!entity) throw 'not_found'
110
+ const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
111
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
112
+ if(JSON.stringify(entityTypeAndIdParts) != JSON.stringify(typeAndIdParts)) {
113
+ throw 'not_authorized'
114
+ }
115
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
116
+ const data = extractObjectData(writeableProperties, properties, entity)
117
+ await App.validation.validate(data, validators, { source: action, action, service, app, client })
118
+ emit({
119
+ type: eventName,
120
+ [modelPropertyName]: id,
121
+ identifiers,
122
+ data
123
+ })
124
+ }
125
+ })
126
+ const action = service.actions[actionName]
127
+ const validators = App.validation.getValidators(action, service, action)
128
+ }
129
+
130
+ function defineDeleteAction(config, context) {
131
+ const {
132
+ service, app, model, modelRuntime, modelPropertyName,
133
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
134
+ } = context
135
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Deleted'
136
+ const actionName = 'delete' + joinedOthersClassName + 'Owned' + modelName
137
+ service.actions[actionName] = new ActionDefinition({
138
+ name: actionName,
139
+ properties: {
140
+ ...(model.properties)
141
+ },
142
+ access: config.deleteAccess || config.writeAccess,
143
+ skipValidation: true,
144
+ //queuedBy: otherPropertyNames,
145
+ waitForEvents: true,
146
+ async execute(properties, { client, service }, emit) {
147
+ const id = properties[modelPropertyName]
148
+ const entity = await modelRuntime().get(id)
149
+ if(!entity) throw new Error('not_found')
150
+ const entityTypeAndIdParts = extractTypeAndIdParts(otherPropertyNames, entity)
151
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
152
+ if(JSON.stringify(entityTypeAndIdParts) != JSON.stringify(typeAndIdParts)) {
153
+ throw new Error('not_authorized')
154
+ }
155
+ emit({
156
+ type: eventName,
157
+ [modelPropertyName]: id
158
+ })
159
+ }
160
+ })
161
+ }
162
+
163
+ function defineSortIndex(context, sortFields) {
164
+ if(!Array.isArray(sortFields)) sortFields = [sortFields]
165
+ console.log("DEFINE SORT INDEX", sortFields)
166
+ const sortFieldsUc = sortFields.map(fd => fd.slice(0, 1).toUpperCase() + fd.slice(1))
167
+ const indexName = 'by' + context.joinedOthersClassName + sortFieldsUc.join('')
168
+ context.model.indexes[indexName] = new IndexDefinition({
169
+ property: [...(context.otherPropertyNames.map(prop => [prop + 'Type', prop])), ...sortFields]
170
+ })
171
+ }
172
+
173
+ module.exports = function(service, app) {
174
+ processModelsAnyAnnotation(service, app, 'itemOfAny', (config, context) => {
175
+
176
+ defineAnyProperties(context.model, context.otherPropertyNames)
177
+ defineAnyIndex(context.model, context.joinedOthersClassName, context.otherPropertyNames)
178
+
179
+ if(config.sortBy) {
180
+ for(const sortFields of config.sortBy) {
181
+ defineSortIndex(context, sortFields)
182
+ }
183
+ }
184
+
185
+ if(config.readAccess) {
186
+ defineView(config, context)
187
+ }
188
+ /// TODO: multiple views with limited fields
189
+
190
+ defineCreatedEvent(config, context)
191
+ defineUpdatedEvent(config, context)
192
+ defineTransferredEvent(config, context)
193
+ defineDeletedEvent(config, context)
194
+
195
+ if(config.setAccess || config.writeAccess) {
196
+ defineCreateAction(config, context)
197
+ }
198
+
199
+ if(config.updateAccess || config.writeAccess) {
200
+ defineUpdateAction(config, context)
201
+ }
202
+
203
+ if(config.resetAccess || config.writeAccess) {
204
+ defineDeleteAction(config, context)
205
+ }
206
+ })
207
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/relations-plugin",
3
- "version": "0.1.12",
3
+ "version": "0.1.15",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,68 @@
1
+ const App = require("@live-change/framework")
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
+
4
+ function defineSetEvent(config, context, generateId) {
5
+ const {
6
+ service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
7
+ } = context
8
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Set'
9
+ service.events[eventName] = new EventDefinition({
10
+ name: eventName,
11
+ execute(properties) {
12
+ const id = generateId(otherPropertyNames, properties.identifiers)
13
+ return modelRuntime().create({ ...properties.data, ...properties.identifiers, id })
14
+ }
15
+ })
16
+ }
17
+
18
+ function defineUpdatedEvent(config, context, generateId) {
19
+ const {
20
+ service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
21
+ } = context
22
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
23
+ service.events[eventName] = new EventDefinition({
24
+ name: eventName,
25
+ execute(properties) {
26
+ const id = generateId(otherPropertyNames, properties.identifiers)
27
+ return modelRuntime().update(id, { ...properties.data, /*...properties.identifiers*/ })
28
+ }
29
+ })
30
+ }
31
+
32
+ function defineTransferredEvent(config, context, generateId) {
33
+ const {
34
+ service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
35
+ } = context
36
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Transferred'
37
+ service.events[eventName] = new EventDefinition({
38
+ name: eventName,
39
+ async execute(properties) {
40
+ const fromId = generateId(otherPropertyNames, properties.from)
41
+ const toId = generateId(otherPropertyNames, properties.to)
42
+ const data = await modelRuntime().get(fromId)
43
+ await modelRuntime().create({
44
+ ...data,
45
+ ...properties.to,
46
+ id: toId
47
+ })
48
+ await modelRunntime().delete(fromId)
49
+ return toId
50
+ }
51
+ })
52
+ }
53
+
54
+ function defineResetEvent(config, context, generateId) {
55
+ const {
56
+ service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
57
+ } = context
58
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Reset'
59
+ service.events[eventName] = new EventDefinition({
60
+ name: eventName,
61
+ execute({ identifiers }) {
62
+ const id = generateId(otherPropertyNames, identifiers)
63
+ return modelRuntime().delete(id)
64
+ }
65
+ })
66
+ }
67
+
68
+ module.exports = { defineSetEvent, defineUpdatedEvent, defineTransferredEvent, defineResetEvent }
package/propertyOf.js CHANGED
@@ -17,7 +17,7 @@ function defineView(config, context) {
17
17
  validation: ['nonEmpty']
18
18
  })
19
19
  }
20
- const viewName = config.name || ((config.prefix ? (prefix + joinedOthersClassName) : joinedOthersPropertyName) +
20
+ const viewName = config.name || ((config.prefix ? (config.prefix + joinedOthersClassName) : joinedOthersPropertyName) +
21
21
  'Owned' + modelName + (config.suffix || ''))
22
22
  service.views[viewName] = new ViewDefinition({
23
23
  name: viewName,
@@ -37,21 +37,9 @@ function defineView(config, context) {
37
37
  })
38
38
  }
39
39
 
40
- async function defineSetEvent(config, context) {
41
- const {
42
- service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
43
- } = context
44
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Set'
45
- service.events[eventName] = new EventDefinition({
46
- name: eventName,
47
- execute(properties) {
48
- const id = generateId(otherPropertyNames, properties.identifiers)
49
- return modelRuntime().create({ ...properties.data, ...properties.identifiers, id })
50
- }
51
- })
52
- }
40
+ const { defineSetEvent, defineUpdatedEvent, defineTransferredEvent, defineResetEvent } = require('./propertyEvents.js')
53
41
 
54
- async function defineSetAction(config, context) {
42
+ function defineSetAction(config, context) {
55
43
  const {
56
44
  service, app, model, defaults,
57
45
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
@@ -81,21 +69,7 @@ async function defineSetAction(config, context) {
81
69
  const validators = App.validation.getValidators(action, service, action)
82
70
  }
83
71
 
84
- async function defineUpdateEvent(config, context) {
85
- const {
86
- service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
87
- } = context
88
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
89
- service.events[eventName] = new EventDefinition({
90
- name: eventName,
91
- execute(properties) {
92
- const id = generateId(otherPropertyNames, properties.identifiers)
93
- return modelRuntime().update(id, { ...properties.data, ...properties.identifiers })
94
- }
95
- })
96
- }
97
-
98
- async function defineUpdateAction(config, context) {
72
+ function defineUpdateAction(config, context) {
99
73
  const {
100
74
  service, app, model, modelRuntime,
101
75
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
@@ -128,21 +102,7 @@ async function defineUpdateAction(config, context) {
128
102
  const validators = App.validation.getValidators(action, service, action)
129
103
  }
130
104
 
131
- async function defineResetEvent(config, context) {
132
- const {
133
- service, modelRuntime, joinedOthersPropertyName, modelName, otherPropertyNames
134
- } = context
135
- const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Reset'
136
- service.events[eventName] = new EventDefinition({
137
- name: eventName,
138
- execute({ identifiers }) {
139
- const id = generateId(otherPropertyNames, identifiers)
140
- return modelRuntime().delete(id)
141
- }
142
- })
143
- }
144
-
145
- async function defineResetAction(config, context) {
105
+ function defineResetAction(config, context) {
146
106
  const {
147
107
  service, modelRuntime, modelPropertyName,
148
108
  otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model
@@ -190,9 +150,10 @@ module.exports = function(service, app) {
190
150
  }
191
151
  }
192
152
 
193
- defineSetEvent(config, context)
194
- defineUpdateEvent(config, context)
195
- defineResetEvent(config, context)
153
+ defineSetEvent(config, context, generateId)
154
+ defineUpdateEvent(config, context, generateId)
155
+ defineTransferEvent(config, context, generateId)
156
+ defineResetEvent(config, context, generateId)
196
157
 
197
158
  if(config.setAccess || config.writeAccess) {
198
159
  defineSetAction(config, context)
@@ -0,0 +1,178 @@
1
+ const App = require("@live-change/framework")
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
+
4
+ const {
5
+ extractObjectData, generateId
6
+ } = require('./utils.js')
7
+
8
+ const {
9
+ extractTypeAndIdParts, extractIdentifiersWithTypes, defineAnyProperties, defineAnyIndex,
10
+ processModelsAnyAnnotation, generateAnyId
11
+ } = require('./utilsAny.js')
12
+
13
+
14
+ function defineView(config, context) {
15
+ const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
16
+ modelName, others, model } = context
17
+ const viewProperties = {}
18
+ for (let i = 0; i < others.length; i++) {
19
+ viewProperties[otherPropertyNames[i]] = new PropertyDefinition({
20
+ type: others[i],
21
+ validation: ['nonEmpty']
22
+ })
23
+ viewProperties[otherPropertyNames[i] + 'Type'] = new PropertyDefinition({
24
+ type: 'String',
25
+ validation: ['nonEmpty']
26
+ })
27
+ }
28
+ const viewName = config.name || ((config.prefix ? (config.prefix + joinedOthersClassName) : joinedOthersPropertyName) +
29
+ 'Owned' + modelName + (config.suffix || ''))
30
+ service.views[viewName] = new ViewDefinition({
31
+ name: viewName,
32
+ properties: {
33
+ ...viewProperties
34
+ },
35
+ returns: {
36
+ type: model,
37
+ },
38
+ access: config.access,
39
+ daoPath(properties, { client, context }) {
40
+ const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
41
+ const id = typeAndIdParts.length > 1 ? typeAndIdParts.map(p => JSON.stringify(p)).join(':') : idParts[0]
42
+ const path = config.fields ? modelRuntime().limitedPath(id, config.fields) : modelRuntime().path(id)
43
+ return path
44
+ }
45
+ })
46
+ }
47
+
48
+ const { defineSetEvent, defineUpdatedEvent, defineTransferredEvent, defineResetEvent } = require('./propertyEvents.js')
49
+
50
+ function defineSetAction(config, context) {
51
+ const {
52
+ service, app, model, defaults,
53
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
54
+ } = context
55
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Set'
56
+ const actionName = 'set' + joinedOthersClassName + 'Owned' + modelName
57
+ service.actions[actionName] = new ActionDefinition({
58
+ name: actionName,
59
+ properties: {
60
+ ...(model.properties)
61
+ },
62
+ access: config.setAccess || config.writeAccess,
63
+ skipValidation: true,
64
+ queuedBy: otherPropertyNames,
65
+ waitForEvents: true,
66
+ async execute(properties, {client, service}, emit) {
67
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
68
+ const data = extractObjectData(writeableProperties, properties, defaults)
69
+ await App.validation.validate(data, validators, { source: action, action, service, app, client })
70
+ emit({
71
+ type: eventName,
72
+ identifiers, data
73
+ })
74
+ }
75
+ })
76
+ const action = service.actions[actionName]
77
+ const validators = App.validation.getValidators(action, service, action)
78
+ }
79
+
80
+ function defineUpdateAction(config, context) {
81
+ const {
82
+ service, app, model, modelRuntime,
83
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
84
+ } = context
85
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Updated'
86
+ const actionName = 'update' + joinedOthersClassName + 'Owned' + modelName
87
+ service.actions[actionName] = new ActionDefinition({
88
+ name: actionName,
89
+ properties: {
90
+ ...(model.properties)
91
+ },
92
+ access: config.updateAccess || config.writeAccess,
93
+ skipValidation: true,
94
+ queuedBy: otherPropertyNames,
95
+ waitForEvents: true,
96
+ async execute(properties, {client, service}, emit) {
97
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
98
+ const id = generateAnyId(otherPropertyNames, properties)
99
+ const entity = await modelRuntime().get(id)
100
+ if (!entity) throw new Error('not_found')
101
+ const data = extractObjectData(writeableProperties, properties, entity)
102
+ await App.validation.validate(data, validators, { source: action, action, service, app, client })
103
+ emit({
104
+ type: eventName,
105
+ identifiers, data
106
+ })
107
+ }
108
+ })
109
+ const action = service.actions[actionName]
110
+ const validators = App.validation.getValidators(action, service, action)
111
+ }
112
+
113
+ function defineResetAction(config, context) {
114
+ const {
115
+ service, modelRuntime, modelPropertyName,
116
+ otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model
117
+ } = context
118
+ const eventName = joinedOthersPropertyName + 'Owned' + modelName + 'Reset'
119
+ const actionName = 'reset' + joinedOthersClassName + 'Owned' + modelName
120
+ service.actions[actionName] = new ActionDefinition({
121
+ name: actionName,
122
+ properties: {
123
+ [modelPropertyName]: {
124
+ type: model,
125
+ validation: ['nonEmpty']
126
+ }
127
+ },
128
+ access: config.resetAccess || config.writeAccess,
129
+ queuedBy: otherPropertyNames,
130
+ waitForEvents: true,
131
+ async execute(properties, {client, service}, emit) {
132
+ const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
133
+ const id = generateAnyId(otherPropertyNames, properties)
134
+ const entity = await modelRuntime().get(id)
135
+ if (!entity) throw new Error('not_found')
136
+ emit({
137
+ type: eventName,
138
+ identifiers
139
+ })
140
+ }
141
+ })
142
+ }
143
+
144
+
145
+
146
+ module.exports = function(service, app) {
147
+ processModelsAnyAnnotation(service, app, 'propertyOf', (config, context) => {
148
+
149
+ defineAnyProperties(context.model, context.otherPropertyNames)
150
+ defineAnyIndex(context.model, context.joinedOthersClassName, context.otherPropertyNames)
151
+
152
+ if(config.readAccess) {
153
+ defineView({ ...config, access: config.readAccess }, context)
154
+ }
155
+ if(config.views) {
156
+ for(const view of config.views) {
157
+ defineView({ ...config, ...view }, context)
158
+ }
159
+ }
160
+
161
+ defineSetEvent(config, context, generateAnyId)
162
+ defineUpdatedEvent(config, context, generateAnyId)
163
+ defineTransferedEvent(config, context, generateId)
164
+ defineResetEvent(config, context, generateAnyId)
165
+
166
+ if(config.setAccess || config.writeAccess) {
167
+ defineSetAction(config, context)
168
+ }
169
+
170
+ if(config.updateAccess || config.writeAccess) {
171
+ defineUpdateAction(config, context)
172
+ }
173
+
174
+ if(config.resetAccess || config.writeAccess) {
175
+ defineResetAction(config, context);
176
+ }
177
+ })
178
+ }
package/utils.js CHANGED
@@ -71,6 +71,7 @@ function processModelsAnnotation(service, app, annotation, cb) {
71
71
  if (model[annotation]) {
72
72
  if (model[annotation + 'Processed']) throw new Error("duplicated processing of " + annotation + " processor")
73
73
  model[annotation + 'Processed'] = true
74
+
74
75
  const originalModelProperties = { ...model.properties }
75
76
  const modelProperties = Object.keys(model.properties)
76
77
  const modelPropertyName = modelName.slice(0, 1).toLowerCase() + modelName.slice(1)
@@ -91,7 +92,7 @@ function processModelsAnnotation(service, app, annotation, cb) {
91
92
  .map(other => other.name ? other.name : other)
92
93
 
93
94
  const writeableProperties = modelProperties || config.writeableProperties
94
- console.log("PPP", others)
95
+ //console.log("PPP", others)
95
96
  const otherPropertyNames = others.map(other => other.slice(0, 1).toLowerCase() + other.slice(1))
96
97
  const joinedOthersPropertyName = otherPropertyNames[0] +
97
98
  (others.length > 1 ? ('And' + others.slice(1).join('And')) : '')
package/utilsAny.js ADDED
@@ -0,0 +1,99 @@
1
+ const App = require("@live-change/framework")
2
+ const { PropertyDefinition, ViewDefinition, IndexDefinition, ActionDefinition, EventDefinition } = App
3
+
4
+ function extractTypeAndIdParts(otherPropertyNames, properties) {
5
+ const typeAndIdParts = []
6
+ for (const propertyName of otherPropertyNames) {
7
+ typeAndIdParts.push(properties[propertyName+'Type'])
8
+ typeAndIdParts.push(properties[propertyName])
9
+ }
10
+ return typeAndIdParts
11
+ }
12
+
13
+ function extractIdentifiersWithTypes(otherPropertyNames, properties) {
14
+ const identifiers = {}
15
+ for (const propertyName of otherPropertyNames) {
16
+ identifiers[propertyName] = properties[propertyName]
17
+ identifiers[propertyName + 'Type'] = properties[propertyName + 'Type']
18
+ }
19
+ return identifiers
20
+ }
21
+
22
+ function generateAnyId(otherPropertyNames, properties) {
23
+ return otherPropertyNames
24
+ .map(p => [p+'Type', p])
25
+ .flat()
26
+ .map(p => JSON.stringify(properties[p])).join(':')
27
+ }
28
+
29
+ function defineAnyProperties(model, names) {
30
+ for (let i = 0; i < types.length; i++) {
31
+ model.properties[names[i]] = new PropertyDefinition({
32
+ type: String,
33
+ validation: ['nonEmpty']
34
+ })
35
+ model.properties[names[i]+'Type'] = new PropertyDefinition({
36
+ type: String,
37
+ validation: ['nonEmpty']
38
+ })
39
+ }
40
+ }
41
+
42
+ function defineAnyIndex(model, what, props) {
43
+ model.indexes['by' + what] = new IndexDefinition({
44
+ property: props.map(prop => [prop+'Type', prop]).flat()
45
+ })
46
+ }
47
+
48
+ function processModelsAnyAnnotation(service, app, annotation, cb) {
49
+ if (!service) throw new Error("no service")
50
+ if (!app) throw new Error("no app")
51
+
52
+ for(let modelName in service.models) {
53
+ const model = service.models[modelName]
54
+
55
+ //console.log("PO", modelName, model[annotation])
56
+
57
+ if (model[annotation]) {
58
+ if (model[annotation + 'Processed']) throw new Error("duplicated processing of " + annotation + " processor")
59
+ model[annotation + 'Processed'] = true
60
+
61
+ const originalModelProperties = { ...model.properties }
62
+ const modelProperties = Object.keys(model.properties)
63
+ const modelPropertyName = modelName.slice(0, 1).toLowerCase() + modelName.slice(1)
64
+ const defaults = App.utils.generateDefault(originalModelProperties)
65
+
66
+ function modelRuntime() {
67
+ return service._runtime.models[modelName]
68
+ }
69
+
70
+ if (!model.indexes) model.indexes = {}
71
+
72
+ let config = model[annotation] // only single ownership is possible, but may be owned by objects set
73
+ if (typeof config == 'string' || Array.isArray(config)) config = {what: config}
74
+
75
+ console.log("MODEL " + modelName + " IS "+ annotation +" " + config.what)
76
+
77
+ const otherPropertyNames = (Array.isArray(config.to) ? config.to : [config.to ?? 'owner'])
78
+ .map(other => other.name ? other.name : other)
79
+
80
+ const writeableProperties = modelProperties || config.writeableProperties
81
+ const others = otherPropertyNames.map(other => other.slice(0, 1).toLowerCase() + other.slice(1))
82
+ const joinedOthersPropertyName = otherPropertyNames[0] +
83
+ (others.length > 1 ? ('And' + others.slice(1).join('And')) : '')
84
+ const joinedOthersClassName = others.join('And')
85
+
86
+ const context = {
87
+ service, app, model, originalModelProperties, modelProperties, modelPropertyName, defaults, modelRuntime,
88
+ otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
89
+ }
90
+
91
+ cb(config, context)
92
+ }
93
+ }
94
+ }
95
+
96
+ module.exports = {
97
+ extractTypeAndIdParts, extractIdentifiersWithTypes, defineAnyProperties, defineAnyIndex,
98
+ processModelsAnyAnnotation, generateAnyId
99
+ }