@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 +60 -0
- package/itemOf.js +7 -43
- package/itemOfAny.js +207 -0
- package/package.json +1 -1
- package/propertyEvents.js +68 -0
- package/propertyOf.js +9 -48
- package/propertyOfAny.js +178 -0
- package/utils.js +2 -1
- package/utilsAny.js +99 -0
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
package/propertyOfAny.js
ADDED
|
@@ -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
|
+
}
|