@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.
- package/boundTo.js +19 -5
- package/boundToAny.js +18 -5
- package/entity.js +164 -62
- package/itemOf.js +11 -4
- package/itemOfAny.js +11 -5
- package/package.json +3 -3
- package/pluralRelationAnyUtils.js +187 -70
- package/pluralRelationUtils.js +277 -114
- package/propertyOf.js +11 -5
- package/propertyOfAny.js +15 -8
- package/relatedTo.js +11 -4
- package/relatedToAny.js +11 -4
- package/singularRelationAnyUtils.js +208 -81
- package/singularRelationUtils.js +222 -77
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
311
|
+
export {
|
|
312
|
+
defineView,
|
|
313
|
+
defineCreateAction, defineUpdateAction, defineDeleteAction,
|
|
314
|
+
defineCreateTrigger, defineUpdateTrigger, defineDeleteTrigger,
|
|
315
|
+
defineSortIndex
|
|
316
|
+
}
|