client_request

model grammar version 97

  1. Request types
    1. Collection query
    2. Acyclic graph tree query
    3. Acyclic graph list query
    4. Mutation
    5. Subscription
    6. Subscription deletion
    7. Command execution
    8. Password mutation
    9. Password reset
  2. Rules

Request types

'type': stategroup (
	'collection query' {
		'context node path': [ on ] component 'id path'
		'collection path': [ from ] component 'collection query path'
		'filters': [ where ] group {
			'todo filter': stategroup (
				'yes' { [ has-todo ]
					'path': component 'conditional path'
				}
				'no' { }
			)
			'property filters': dictionary {
				'path': [ : ] component 'conditional path'
				'property': [ . ] reference
				'type': stategroup (
					'number' {
						'expression': component 'number filter expression'
					}
					'state group' { [ in ]
						'states to include': [ (, ) ] dictionary { [ ? ] }
					}
					'text' {
						'type': stategroup (
							'simple' { [ (, ) ]
								'expression': component 'filter expression'
							}
							'reference' {
								'operator': stategroup (
									'in' { [ in ] }
									'not in' { [ not in ] }
								)
								'references': [ (, ) ] component 'reference filter list'
							}
						)
					}
					'collection' {
						'operator': stategroup (
							'in' { [ in ] }
							'not in' { [ not in ] }
						)
						'keys': [ (, ) ] dictionary { [ [, ] ] }
					}
				)
			}
		}
		'select entries': stategroup (
			'yes' { [ select ]
				'properties': component 'node query'
				'limit number of entries': [ limit ] integer
			}
			'no' { }
		)
		'aggregates': [ aggregate ] dictionary {
			'type': [ : ] stategroup (
				'state distribution' { [ distribution ]
					'path': component 'conditional path'
					'state group': [ . ] reference
				}
			)
		}
	}
	'acyclic graph tree query' {
		'context node': [ graph ] component 'id path'
		'type': [ select ] stategroup (
			'collection' { [ from ]
				'graph': reference
			}
		)
	}
	'acyclic graph list query' {
		'context node': [ on ] component 'id path'
		'entry points': [ from ] component 'entry point path'
		'graph': [ flatten ] reference
		'query': [ select ] group {
			'collection path': component 'collection path'
			'properties': dictionary {
				'path': [ = ] component 'conditional path'
				'type': stategroup (
					'number' { [ # ]
						'number': reference
					}
					'text' { [ . ]
						'text': reference
					}
					'state group' { [ ? ]
						'state group': reference
					}
				)
			}
		}
	}
	'mutation' {
		'context node': [ update ] component 'id path'
		'node update': component 'node update'
	}
	'subscription' {
		'mutation permissions': stategroup (
			'include' { }
			'ignore' { [ #ignore-mutation-permissions ] }
		)
		'context node': [ subscribe to ] component 'id path'
		'node subscription': component 'node subscription'
	}
	'subscription deletion' { }
	'command execution' {
		'context node': [ execute ] component 'id path'
		'command': [ : ] reference
		'arguments': [ with ] component 'node initialization'
	}
	'password mutation' { [ change password ]
		'old password': [ from ] text
		'new password': [ to ] text
	}
	'password reset' { [ reset password ]
		'username': [ of ] text
	}
)

Collection query

Queries an hierarchy of collections and produces a select and/or aggregate result the entries that match the filters.

Acyclic graph tree query

Produces a dependency tree showing the dependencies of a node in a predefined ‘graph’. The ‘context node’ is the root of the tree.

Acyclic graph list query

Queries a collection of references and create a flat subgraph of the provided ‘graph’ for each of them. The ‘query’ group defines what data will be queried for each of the entries.

For example, suppose we have this model, specifying Products and Orders:

'Products': collection ['Name']
	'assembly': acyclic-graph
{
	'Name': text
	'Parts': collection ['Product'] {
		'Product': text -> ^ sibling in ('assembly')
		'Price': number positive 'euro'
	}
}
'Orders': collection ['ID'] {
	'ID': text
	'Products': collection ['Product'] {
		'Product': text -> ^ ^ .'Products'
	}
}

And the following query:

on /* root */
from .'Orders'.'Products'>'Product'
flatten 'assembly'
select .'Parts'
	'PP': = #'Price'

Then we get a result of the form:

'Orders': (
	['A'] (
		'Products': (
			subgraph ['1'] = ( // flat subgraph:
				['1'] (
					count = 0
					'Parts' = (
						['1.1'] ( 'PP' = 10 )
						['1.2'] ( 'PP' = 20 )
					)
				) // root of the graph
				['1.1'] ( count = 2 'Parts' = ( ) )
				['1.2'] ( count = 1 'Parts' = ( ) )
			)
		)
	)
	['B'] (
		'Products': (
			['2'] ( ['2'] ( count = 0 'Parts' = ( ) ) )
		)
	)
)

Mutation

Updates specified parts of your data.

Subscription

Subscribes to specific pieces of data. The subscriber will get notifications in case subscribed data are modified.

Subscription deletion

Request unsubscribe, and thus halt notifications for a subscription.

Command execution

Request to execute a command as defined in an application model.

Password mutation

Updates a user’s password.

Password reset

Resets a user’s password.

Rules

'filter expression' {
	'type': stategroup (
		'wildcard' { [ * ] }
		'alternatives' { [ [, ] ]
			'alternatives': dictionary { }
		}
	)
	'has more steps': stategroup (
		'yes' {
			'tail': component 'filter expression'
		}
		'no' { }
	)
}
'number filter expression' {
	'operator': stategroup (
		'range' {
			'greater than': stategroup (
				'yes' { [ > ]
					'criterium': integer
				}
				'no' { }
			)
			'less than': stategroup (
				'yes' { [ < ]
					'criterium': integer
				}
				'no' { }
			)
		}
		'equals' { [ == ]
			'criterium': integer
		}
	)
}
'reference filter list' {
	'referenced node': component 'id path'
	'has alternative': stategroup (
		'yes' {
			'alternative': [ , ] component 'reference filter list'
		}
		'no' { }
	)
}
'id path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'collection entry' { [ . ]
					'collection': reference
					'id': [ [, ] ] text
				}
				'group' { [ . ]
					'group': reference
				}
				'state' {
					'state group': [ . ] reference
					'state': [ ? ] reference
				}
			)
			'tail': component 'id path'
		}
	)
}
'conditional child path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'group' { [ + ]
					'group': reference
				}
				'state' { [ ? ]
					'state group': reference
					'state': [ | ] reference
				}
			)
			'tail': component 'conditional child path'
		}
	)
}
'collection path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'head': component 'conditional child path'
			'collection': [ . ] reference
			'tail': component 'collection path'
		}
	)
}
'collection query path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'head': component 'conditional child path'
			'collection': [ . ] reference
			'type': stategroup (
				'candidates' { [ candidates ]
					'include reference': stategroup (
						'yes' { [ #include-reference ] }
						'no' { }
					)
				}
				'existing entries' { }
			)
			'tail': component 'collection query path'
		}
	)
}
'entry point path' {
	'has steps': stategroup (
		'no' {
			'text': [ > ] reference
		}
		'yes' {
			'head': component 'conditional child path'
			'collection': [ . ] reference
			'tail': component 'entry point path'
		}
	)
}
'conditional path' {
	'head': component 'singular path'
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'state' {
					'state group': [ . ] reference
					'state': [ ? ] reference
				}
				'collection entry' {
					'collection': [ . ] reference
					'entry key': [ [, ] ] text
				}
				'link' {
					'text': [ ~> ] reference
				}
			)
			'tail': component 'conditional path'
		}
	)
}
'singular path' {
	'has steps': stategroup (
		'no' { }
		'yes' {
			'type': stategroup (
				'parent' { [ ^ ] }
				'state constraint' { [ .& ]
					'rule': reference
				}
				'property rule' {
					'property': [ . ] reference
					'rule': [ & ] reference
				}
				'reference' {
					'text': [ > ] reference
				}
				'group' {
					'group': [ + ] reference
				}
			)
			'tail': component 'singular path'
		}
	)
}
'aggregate' {
	'head': component 'singular path'
	'collection': [ . ] reference
	'tail': component 'conditional path'
}
'number aggregate' {
	'aggregate': component 'aggregate'
	'property name': [ . ] reference
}
'signed number property' {
	'sign': stategroup (
		'negative' { [ - ] }
		'positive' { }
	)
	'path': component 'singular path'
	'property name': [ . ] reference
}
'signed number property list' {
	'has element': stategroup (
		'no' { }
		'yes' {
			'signed number property': component 'signed number property'
			'tail': component 'signed number property list'
		}
	)
}
'number expression' {
	'type': stategroup (
		'value' {
			'value': integer
		}
		'number property' {
			'signed number property': component 'signed number property'
		}
		'sum' { [ sum ]
			'number aggregate': component 'number aggregate'
		}
		'sum list' { [ sum ]
			'numbers': [ (, ) ] component 'signed number property list'
		}
		'remainder' { [ remainder ]
			'number': [ ( ] component 'signed number property'
			'modulus': [ ,, ) ] component 'signed number property'
		}
		'product' { [ product ]
			'numbers': [ (, ) ] component 'signed number property list'
		}
		'division' { [ division ]
			'rounding': stategroup (
				'ordinary' { }
				'ceil' { [ ceil ] }
				'floor' { [ floor ] }
			)
			'numerator': [ ( ] component 'signed number property'
			'denominator': [ ,, ) ] component 'signed number property'
		}
		'count' { [ count ]
			'aggregate': component 'aggregate'
		}
		'state based' { [ switch ( ]
			'path': component 'singular path'
			'state group': [ ?, ) ] reference
			'states': [ (, ) ] dictionary { [ | ]
				'value': [ = ] component 'number expression'
			}
		}
		'maximum' { [ max ]
			'left expression': [ ( ] component 'number expression'
			'right expression': [ ,, ) ] component 'number expression'
		}
		'minimum' { [ min ]
			'left expression': [ ( ] component 'number expression'
			'right expression': [ ,, ) ] component 'number expression'
		}
	)
}
'singular text expression' {
	'type': stategroup (
		'static' {
			'string': text
		}
		'dynamic' {
			'path': component 'singular path'
			'text': [ . ] reference
		}
	)
}
'singular text expression list' {
	'has element': stategroup (
		'no' { }
		'yes' {
			'singular text expression': component 'singular text expression'
			'tail': component 'singular text expression list'
		}
	)
}
'text expression' {
	'type': stategroup (
		'singular' {
			'expression': component 'singular text expression'
		}
		'concatenation' { [ concat ]
			'parts': [ (, ) ] component 'singular text expression list'
		}
	)
}
'node subscription' { [ (, ) ]
	'attributes': dictionary {
		'type': [ : ] stategroup (
			'property' {
				'type': stategroup (
					'collection' { [ collection ]
						'include graph endpoints': stategroup (
							'no' { }
							'yes' { [ #include-graph-endpoints ] }
						)
						'subscribe on': stategroup (
							'entries' {
								'key filter': stategroup (
									'no' { }
									'yes' {
										'keys': [ [, ] ] dictionary { }
									}
								)
								'subscription': component 'node subscription'
							}
							'updates' { }
						)
					}
					'group' { [ group ]
						'subscription': component 'node subscription'
					}
					'number' { [ number ] }
					'state group' { [ stategroup ]
						'states': [ (, ) ] dictionary {
							'subscription': component 'node subscription'
						}
					}
					'text' { [ text ]
						'include reference': stategroup (
							'no' { }
							'yes' { [ #include-reference ] }
						)
					}
					'file' { [ file ] }
				)
			}
			'command' { [ command ] }
		)
	}
}
'node update' { [ (, ) ]
	'properties': dictionary {
		'type': [ : ] stategroup (
			'group' { [ group ]
				'update': component 'node update'
			}
			'number' { [ number ]
				'new value': [ = ] integer
			}
			'state group' { [ stategroup ]
				'state': reference
				'type': stategroup (
					'set' { [ = ]
						'initialization': component 'node initialization'
					}
					'update' {
						'update': component 'node update'
					}
				)
			}
			'text' { [ text = ]
				'new value': text
			}
			'file' { [ file = ]
				'new token': text
				'new extension': [ . ] text
			}
			'collection' { [ collection ]
				'entries': [ (, ) ] dictionary {
					'type': stategroup (
						'create' { [ create ]
							'initialization': component 'node initialization'
						}
						'update' {
							'update': component 'node update'
						}
						'remove' { [ remove ] }
					)
				}
			}
		)
	}
}
'node initialization' { [ (, ) ]
	'properties': dictionary {
		'type': [ : ] stategroup (
			'group' { [ group ]
				'initialization': [ = ] component 'node initialization'
			}
			'number' { [ number ]
				'value': [ = ] integer
			}
			'state group' { [ stategroup ]
				'state': [ = ] reference
				'initialization': component 'node initialization'
			}
			'text' { [ text = ]
				'value': text
			}
			'file' { [ file = ]
				'token': text
				'extension': [ . ] text
			}
			'collection' { [ collection ]
				'entries': [ (, ) ] dictionary {
					'initialization': component 'node initialization'
				}
			}
		)
	}
}
'node query' { [ (, ) ]
	'properties': dictionary {
		'path': [ : ] component 'conditional path'
		'type': stategroup (
			'id path' { [ id-path ] }
			'number' { [ number ]
				'expression': [ = ] component 'number expression'
			}
			'text' { [ text ]
				'expression': [ = ] component 'text expression'
			}
			'file' { [ file ]
				'file': [ = / ] reference
			}
			'state group' { [ stategroup ]
				'state group': [ = . ] reference
			}
			'collection' { [ collection ]
				'collection': [ = . ] reference
				'include graph endpoints': stategroup (
					'no' { }
					'yes' { [ #include-graph-endpoints ] }
				)
				'properties': component 'node query'
			}
		)
	}
}