@live-change/relations-plugin 0.9.198 → 0.9.200

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/relations-plugin",
3
- "version": "0.9.198",
3
+ "version": "0.9.200",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "type": "module",
24
24
  "dependencies": {
25
- "@live-change/framework": "^0.9.198",
25
+ "@live-change/framework": "^0.9.200",
26
26
  "pluralize": "^8.0.0"
27
27
  },
28
28
  "devDependencies": {
@@ -30,5 +30,5 @@
30
30
  "typedoc-plugin-markdown": "^4.6.3",
31
31
  "typedoc-plugin-rename-defaults": "^0.7.3"
32
32
  },
33
- "gitHead": "7e485dcbaa2af7fb17052a40238210dc8bdf0c09"
33
+ "gitHead": "a509834e600a546297faa7d1534b6f52e66d2e66"
34
34
  }
@@ -9,10 +9,10 @@ async function fireChangeTriggers(context, objectType, identifiers, object, oldD
9
9
  const { service, modelName, app } = context
10
10
  //if(!trigger) trigger = (...args) => app.trigger(...args)
11
11
  assert(trigger, "trigger is required")
12
- const changeType = data ? (oldData ? 'update' : 'create') : 'delete'
13
- //console.log("FIRE CHANGE TRIGGERS", { context, objectType, identifiers, object, oldData, data })
14
- //console.trace()
12
+ const changeType = data ? (oldData ? 'update' : 'create') : 'delete'
15
13
  const triggerParameters = { objectType, object, identifiers, data, oldData, changeType }
14
+ //console.log("FIRE CHANGE TRIGGERS", triggerParameters)
15
+ //console.trace()
16
16
  await Promise.all([
17
17
  trigger({
18
18
  type: changeType + service.name[0].toUpperCase() + service.name.slice(1) + '_' + modelName,
@@ -32,7 +32,7 @@ async function fireChangeTriggers(context, objectType, identifiers, object, oldD
32
32
  async function iterateChildren(context, propertyName, path, cb) {
33
33
  const {
34
34
  service, modelRuntime, objectType: myType, writeableProperties, modelName,
35
- reverseRelationWord, app, otherPropertyNames, sameIdAsParent
35
+ reverseRelationWord, app, otherPropertyNames, sameIdAsParent, isAny
36
36
  } = context
37
37
  assert(modelRuntime, "modelRuntime is required")
38
38
  assert(modelRuntime().sortedIndexRangeGet, "sortedIndexRangeGet is required")
@@ -41,7 +41,8 @@ async function iterateChildren(context, propertyName, path, cb) {
41
41
  assert(path, "path is required")
42
42
  assert(cb, "cb is required")
43
43
  if(sameIdAsParent) {
44
- const entity = await modelRuntime().get(path)
44
+ const id = Array.isArray(path) ? (path.length > 1 ? path.map(p => JSON.stringify(p)).join(':') : path[0]) : path
45
+ const entity = await modelRuntime().get(id)
45
46
  if(entity) await cb(entity)
46
47
  } else {
47
48
  const indexName = 'by' + propertyName[0].toUpperCase() + propertyName.slice(1)
@@ -72,7 +73,7 @@ async function triggerDeleteOnParentDeleteTriggers(
72
73
  } = context
73
74
 
74
75
  let found = false
75
- await iterateChildren(context, propertyName, path, async entity => {
76
+ await iterateChildren(context, propertyName, path, async entity => {
76
77
  found = true
77
78
  const identifiers = extractIdentifiers(otherPropertyNames, entity)
78
79
  await fireChangeTriggers(context, myType, identifiers, entity.id,
@@ -65,7 +65,7 @@ export function entityAccessControl({service, modelName, modelPropertyName}, acc
65
65
  export function defineView(config, context, external) {
66
66
  const { service, modelRuntime, modelPropertyName, modelName, model } = context
67
67
  const viewName = (config.prefix || '' ) + (config.prefix ? modelName : modelPropertyName) + (config.suffix || '')
68
- if(external) model.crud.read = viewName
68
+ if(external) model.crud.read ??= viewName
69
69
  const view = service.view({
70
70
  name: viewName,
71
71
  properties: {
@@ -186,7 +186,7 @@ export function defineCreateAction(config, context) {
186
186
  modelName, writeableProperties
187
187
  } = context
188
188
  const actionName = 'create' + modelName
189
- model.crud.create = actionName
189
+ model.crud.create ??= actionName
190
190
  const action = (service as ServiceDefinition<ServiceDefinitionSpecification>).action<ActionDefinitionSpecificationAC>({
191
191
  name: actionName,
192
192
  properties: { ...model.properties },
@@ -255,7 +255,7 @@ export function defineUpdateAction(config, context) {
255
255
  modelName, writeableProperties
256
256
  } = context
257
257
  const actionName = 'update' + modelName
258
- model.crud.update = actionName
258
+ model.crud.update ??= actionName
259
259
  const action = new ActionDefinition({
260
260
  name: actionName,
261
261
  properties: {
@@ -328,7 +328,7 @@ export function defineDeleteAction(config, context) {
328
328
  modelName, writeableProperties
329
329
  } = context
330
330
  const actionName = 'delete' + modelName
331
- model.crud.delete = actionName
331
+ model.crud.delete ??= actionName
332
332
  service.actions[actionName] = new ActionDefinition({
333
333
  name: actionName,
334
334
  properties: {
@@ -75,7 +75,7 @@ function defineSingleView(config, context, external = true) {
75
75
  sourceAccessControl, [modelPropertyName], [objectType]
76
76
  )
77
77
  const viewName = modelName[0].toLowerCase() + modelName.slice(1)
78
- model.crud.read = viewName
78
+ model.crud.read ??= viewName
79
79
  service.view({
80
80
  name: viewName,
81
81
  properties: {
@@ -125,7 +125,7 @@ function defineCreateAction(config, context) {
125
125
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
126
126
  } = context
127
127
  const actionName = 'create' + modelName
128
- model.crud.create = actionName
128
+ model.crud.create ??= actionName
129
129
  const sourceAccessControl = config.createAccessControl || config.writeAccessControl
130
130
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames)
131
131
  const action = new ActionDefinition({
@@ -225,7 +225,7 @@ function defineUpdateAction(config, context) {
225
225
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
226
226
  } = context
227
227
  const actionName = 'update' + modelName
228
- model.crud.update = actionName
228
+ model.crud.update ??= actionName
229
229
  const sourceAccessControl = config.updateAccessControl || config.writeAccessControl
230
230
  const accessControl = cloneAndPrepareSingleAccessControl(
231
231
  sourceAccessControl, [modelPropertyName], [objectType]
@@ -313,7 +313,7 @@ function defineDeleteAction(config, context) {
313
313
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
314
314
  } = context
315
315
  const actionName = 'delete' + modelName
316
- model.crud.delete = actionName
316
+ model.crud.delete ??= actionName
317
317
  const sourceAccessControl = config.deleteAccessControl || config.writeAccessControl
318
318
  const accessControl = cloneAndPrepareSingleAccessControl(
319
319
  sourceAccessControl, [modelPropertyName], [objectType]
@@ -66,7 +66,7 @@ function defineSingleView(config, context, external = true) {
66
66
  validation: ['nonEmpty']
67
67
  })
68
68
  const viewName = modelName[0].toLowerCase() + modelName.slice(1)
69
- model.crud.read = viewName
69
+ model.crud.read ??= viewName
70
70
  const sourceAccessControl = external && (config.readAccessControl || config.writeAccessControl)
71
71
  const accessControl = cloneAndPrepareAccessControl(
72
72
  sourceAccessControl, [modelPropertyName], [objectType]
@@ -120,7 +120,7 @@ function defineCreateAction(config, context) {
120
120
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
121
121
  } = context
122
122
  const actionName = 'create' + modelName
123
- model.crud.create = actionName
123
+ model.crud.create ??= actionName
124
124
  const sourceAccessControl = config.createAccessControl || config.writeAccessControl
125
125
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames, others)
126
126
  const action = new ActionDefinition({
@@ -204,7 +204,7 @@ function defineUpdateAction(config, context) {
204
204
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
205
205
  } = context
206
206
  const actionName = 'update' + modelName
207
- model.crud.update = actionName
207
+ model.crud.update ??= actionName
208
208
  const sourceAccessControl = config.updateAccessControl || config.writeAccessControl
209
209
  const accessControl = cloneAndPrepareAccessControl(
210
210
  sourceAccessControl, [modelPropertyName], [objectType]
@@ -290,7 +290,7 @@ function defineDeleteAction(config, context) {
290
290
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
291
291
  } = context
292
292
  const actionName = 'delete' + modelName
293
- model.crud.delete = actionName
293
+ model.crud.delete ??= actionName
294
294
  const sourceAccessControl = config.deleteAccessControl || config.writeAccessControl
295
295
  const accessControl = cloneAndPrepareAccessControl(
296
296
  sourceAccessControl, [modelPropertyName], [objectType]
package/src/propertyOf.ts CHANGED
@@ -60,7 +60,7 @@ export default function(service, app) {
60
60
  context.reverseRelationWord = 'Owned'
61
61
  context.partialReverseRelationWord = 'Owned'
62
62
 
63
- context.sameIdAsParent = true
63
+ context.sameIdAsParent = context.otherPropertyNames.length === 1
64
64
 
65
65
  context.identifiers = defineProperties(context.model, context.others, context.otherPropertyNames)
66
66
  context.model.identifiers = [
@@ -64,7 +64,7 @@ export default function(service, app) {
64
64
  context.reverseRelationWord = 'Owned'
65
65
  context.partialReverseRelationWord = 'Owned'
66
66
 
67
- context.sameIdAsParent = true
67
+ context.sameIdAsParent = context.otherPropertyNames.length === 1
68
68
 
69
69
  context.identifiers = defineAnyProperties(context.model, context.otherPropertyNames, config)
70
70
  context.model.identifiers = [
@@ -16,31 +16,37 @@ import { fireChangeTriggers } from "./changeTriggers.js"
16
16
 
17
17
  import pluralize from 'pluralize'
18
18
 
19
- export function createIdentifiersProperties(keys) {
19
+ export function createIdentifiersProperties(keys, idField) {
20
20
  const identifiers = {}
21
21
  if(keys) for(const key of keys) {
22
22
  identifiers[key + 'Type'] = {
23
23
  type: String,
24
- validation: ['nonEmpty']
24
+ validation: idField ? [{ name: 'ifEmpty', prop: idField, then: ['nonEmpty'] }] : ['nonEmpty']
25
25
  }
26
26
  identifiers[key] = {
27
27
  type: String,
28
- validation: ['nonEmpty']
28
+ validation: idField ? [{ name: 'ifEmpty', prop: idField, then: ['nonEmpty'] }] : ['nonEmpty']
29
29
  }
30
30
  }
31
+ if(idField) identifiers[idField] = {
32
+ type: String,
33
+ validation: keys.map(key => ({ name: 'ifEmpty', prop: key+'Type', then: ['nonEmpty'] }))
34
+ }
31
35
  return identifiers
32
36
  }
33
37
 
34
38
  function defineObjectView(config, context, external = true) {
35
39
  const { service, modelRuntime, otherPropertyNames, joinedOthersPropertyName, joinedOthersClassName,
36
- modelName, others, model } = context
37
- const viewProperties = createIdentifiersProperties(otherPropertyNames)
40
+ modelName, others, model, modelPropertyName } = context
41
+ const viewProperties = createIdentifiersProperties(otherPropertyNames, modelPropertyName)
38
42
  const sourceAccessControl = external
39
43
  && (config.singleAccessControl || config.readAccessControl || config.writeAccessControl)
40
- const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames)
44
+ const accessControl = cloneAndPrepareAccessControl(sourceAccessControl,
45
+ otherPropertyNames.concat(modelPropertyName),
46
+ new Array(otherPropertyNames.length).fill(undefined).concat(model))
41
47
  const viewName = config.name
42
48
  || ((config.prefix ? config.prefix + modelName : modelName[0].toLowerCase() + modelName.slice(1)) + (config.suffix || ''))
43
- model.crud.read = viewName
49
+ model.crud.read ??= viewName
44
50
  service.view({
45
51
  name: viewName,
46
52
  properties: {
@@ -54,6 +60,11 @@ function defineObjectView(config, context, external = true) {
54
60
  global: config.globalView,
55
61
  accessControl,
56
62
  daoPath(properties, { client, context }) {
63
+ const idProp = modelPropertyName ? properties[modelPropertyName] : null
64
+ if(idProp) {
65
+ const path = config.fields ? modelRuntime().limitedPath(idProp, config.fields) : modelRuntime().path(idProp)
66
+ return path
67
+ }
57
68
  const typeAndIdParts = extractTypeAndIdParts(otherPropertyNames, properties)
58
69
  const id = typeAndIdParts.length > 1 ? typeAndIdParts.map(p => JSON.stringify(p)).join(':') : typeAndIdParts[0]
59
70
  const path = config.fields ? modelRuntime().limitedPath(id, config.fields) : modelRuntime().path(id)
@@ -106,7 +117,6 @@ function getSetFunction( validators, validationContext, config, context) {
106
117
  return async function execute(properties, { client, service, trigger }, emit) {
107
118
  const identifiers = extractIdentifiersWithTypes(otherPropertyNames, properties)
108
119
  const id = generateAnyId(otherPropertyNames, properties)
109
- const entity = await modelRuntime().get(id)
110
120
  const data = extractObjectData(writeableProperties, properties,
111
121
  App.computeDefaults(model, properties, { client, service } ))
112
122
  await App.validation.validate({ ...identifiers, ...data }, validators,
@@ -126,7 +136,7 @@ function defineSetAction(config, context) {
126
136
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
127
137
  } = context
128
138
  const actionName = 'set' + modelName
129
- model.crud.create = actionName
139
+ model.crud.create ??= actionName
130
140
  const sourceAccessControl = config.setAccessControl || config.writeAccessControl
131
141
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames)
132
142
  const action = new ActionDefinition({
@@ -201,7 +211,7 @@ function defineUpdateAction(config, context) {
201
211
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
202
212
  } = context
203
213
  const actionName = 'update' + modelName
204
- model.crud.update = actionName
214
+ model.crud.update ??= actionName
205
215
  const sourceAccessControl = config.updateAccessControl || config.writeAccessControl
206
216
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames)
207
217
  const action = new ActionDefinition({
@@ -280,7 +290,7 @@ function defineSetOrUpdateAction(config, context) {
280
290
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName
281
291
  } = context
282
292
  const actionName = 'setOrUpdate' + modelName
283
- model.crud.createOrUpdate = actionName
293
+ model.crud.createOrUpdate ??= actionName
284
294
  const sourceAccessControl = config.setOrUpdateAccessControl || config.writeAccessControl
285
295
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames)
286
296
  const action = new ActionDefinition({
@@ -378,7 +388,7 @@ function defineResetTrigger(config, context) {
378
388
  otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model
379
389
  } = context
380
390
  const actionName = 'reset' + modelName
381
- model.crud.reset = actionName
391
+ model.crud.reset ??= actionName
382
392
  const triggerName = `${service.name}_${actionName}`
383
393
  service.triggers[triggerName] = [new TriggerDefinition({
384
394
  name: triggerName,
@@ -397,7 +407,7 @@ function defineDeleteAction(config, context) {
397
407
  otherPropertyNames, joinedOthersPropertyName, modelName, joinedOthersClassName, model
398
408
  } = context
399
409
  const actionName = 'delete' + modelName
400
- model.crud.delete = actionName
410
+ model.crud.delete ??= actionName
401
411
  const sourceAccessControl = config.resetAccessControl || config.writeAccessControl
402
412
  const accessControl = cloneAndPrepareAccessControl(
403
413
  sourceAccessControl, [modelPropertyName], [objectType]
@@ -39,7 +39,7 @@ export function defineObjectView(config, context, external = true) {
39
39
  const viewProperties = createIdentifiersProperties(otherPropertyNames, others, modelPropertyName)
40
40
  const viewName = config.name
41
41
  || ((config.prefix ? config.prefix + modelName : modelName[0].toLowerCase() + modelName.slice(1)) + (config.suffix || ''))
42
- model.crud.read = viewName
42
+ model.crud.read ??= viewName
43
43
  const sourceAccessControl = external && (config.singleAccessControl || config.readAccessControl || config.writeAccessControl)
44
44
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl,
45
45
  otherPropertyNames.concat(modelPropertyName),
@@ -174,7 +174,7 @@ export function defineSetAction(config, context) {
174
174
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
175
175
  } = context
176
176
  const actionName = 'set' + modelName
177
- model.crud.create = actionName
177
+ model.crud.create ??= actionName
178
178
  const sourceAccessControl = config.setAccessControl || config.writeAccessControl
179
179
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames, others)
180
180
  const action = new ActionDefinition({
@@ -250,7 +250,7 @@ export function defineUpdateAction(config, context) {
250
250
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
251
251
  } = context
252
252
  const actionName = 'update' + modelName
253
- model.crud.update = actionName
253
+ model.crud.update ??= actionName
254
254
  const sourceAccessControl = config.updateAccessControl || config.writeAccessControl
255
255
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames, others)
256
256
  const action = new ActionDefinition({
@@ -328,7 +328,7 @@ export function defineSetOrUpdateAction(config, context) {
328
328
  otherPropertyNames, joinedOthersPropertyName, modelName, writeableProperties, joinedOthersClassName, others
329
329
  } = context
330
330
  const actionName = 'setOrUpdate' + modelName
331
- model.crud.createOrUpdate = actionName
331
+ model.crud.createOrUpdate ??= actionName
332
332
  const sourceAccessControl = config.updateAccessControl || config.writeAccessControl
333
333
  const accessControl = cloneAndPrepareAccessControl(sourceAccessControl, otherPropertyNames, others)
334
334
  const action = new ActionDefinition({
@@ -464,7 +464,7 @@ export function defineResetAction(config, context) {
464
464
  joinedOthersClassName, model, others, writeableProperties
465
465
  } = context
466
466
  const actionName = 'reset' + modelName
467
- model.crud.delete = actionName
467
+ model.crud.delete ??= actionName
468
468
  const properties = {}
469
469
  for (let i = 0; i < others.length; i++) {
470
470
  properties[otherPropertyNames[i]] = new PropertyDefinition({
package/src/utils.ts CHANGED
@@ -256,7 +256,7 @@ export function prepareAccessControl(accessControl: AccessControlSettings, names
256
256
  ac.objects = ac.objects ?? ((params) => names.map((name, index) => ({
257
257
  objectType: types[index],
258
258
  object: params[name]
259
- })).filter(obj => obj.object))
259
+ })).filter(obj => obj.object && obj.objectType))
260
260
  ac.objParams = { names, types }
261
261
  }
262
262
  }
@@ -274,6 +274,7 @@ export function cloneAndPrepareAccessControl(accessControl: AccessControlSetting
274
274
  export function defineDeleteByOwnerEvents(config: RelationConfig, context: RelationContext) {
275
275
  const {
276
276
  service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName, otherPropertyNames,
277
+ sameIdAsParent
277
278
  } = context
278
279
  for(const propertyName of otherPropertyNames) {
279
280
  const eventName = modelName + 'DeleteByOwner'
@@ -287,6 +288,9 @@ export function defineDeleteByOwnerEvents(config: RelationConfig, context: Relat
287
288
  },
288
289
  async execute({owner}) {
289
290
  const runtime = modelRuntime()
291
+ if(sameIdAsParent) {
292
+ return await runtime.delete(owner)
293
+ }
290
294
  const tableName = runtime.tableName
291
295
  const prefix = JSON.stringify(owner)
292
296
  const indexName = tableName + '_by' + propertyName[0].toUpperCase() + propertyName.slice(1)
@@ -349,7 +353,7 @@ export function defineGlobalRangeView(config: {
349
353
  prefix
350
354
  + pluralize(prefix ? modelName : modelPropertyName)
351
355
  + (config.suffix || '')
352
- if(external) model.crud.range = viewName
356
+ if(external) model.crud.range ??= viewName
353
357
  service.views[viewName] = new ViewDefinition({
354
358
  name: viewName,
355
359
  properties: {
package/src/utilsAny.ts CHANGED
@@ -225,7 +225,7 @@ export function prepareAccessControl(accessControl, names, types = undefined) {
225
225
  accessControl.objects = accessControl.objects ?? ((params) => names.map((name, index) => ({
226
226
  objectType: types?.[index] ?? params[name + 'Type'],
227
227
  object: params[name]
228
- })))
228
+ })).filter(obj => obj.object && obj.objectType))
229
229
  }
230
230
  }
231
231
 
@@ -241,7 +241,8 @@ export function cloneAndPrepareAccessControl(accessControl, names, types = undef
241
241
 
242
242
  export function defineDeleteByOwnerEvents(config, context) {
243
243
  const {
244
- service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName, otherPropertyNames, reverseRelationWord
244
+ service, modelRuntime, joinedOthersPropertyName, modelName, modelPropertyName, otherPropertyNames,
245
+ reverseRelationWord, sameIdAsParent
245
246
  } = context
246
247
  for(const propertyName of otherPropertyNames) {
247
248
  const eventName = modelName + 'DeleteByOwner'
@@ -259,6 +260,9 @@ export function defineDeleteByOwnerEvents(config, context) {
259
260
  },
260
261
  async execute({ ownerType, owner }) {
261
262
  const runtime = modelRuntime()
263
+ if(sameIdAsParent) {
264
+ return await runtime.delete(JSON.stringify(ownerType) + ':' + JSON.stringify(owner))
265
+ }
262
266
  const tableName = runtime.tableName
263
267
  const prefix = JSON.stringify(ownerType) + ':' + JSON.stringify(owner)
264
268
  const indexName = tableName + '_by' + propertyName[0].toUpperCase() + propertyName.slice(1)