Recipes
The recipe language describes how fields (or more generally: variables) are evaluated. In the context of Brezel, recipes bind a field’s value to the values of other fields that are referenced in the recipe. For example, it allows you to automatically calculate totals in invoices, define field values inside workflows, and even evaluate expressions inside bakery planner configuration files.
You can test recipes in the Brezel CLI by opening the interactive shell or by opening the DevTools in the Brezel UI and evaluating the recipe in the console.
Syntax
The syntax of the recipe language is based on the EcmaScript syntax with a few additions. Supported are mathematical, logical and bitshift operations, function calls, property, subscript and method access and of course common literals.
Math and logic
Say we want a field total
to always be the sum of two other fields net
and tax
. Then we define the recipe of total
to be:
If we do not know the total tax but the tax rate, we write something like:
and if we know that the tax rate is constant, we can of course write:
These operations work the same way you are probably accustomed to from other languages or Excel. We can also test for truth values:
would return either true
or false
. We can also negate the result:
Testing for equality is done using ==
:
And its negation
or
This would return true
if and only if net
is not equal to 10.
We can also test multiple conditions:
Would return true if net
is below 10.25 and greater than 5.75.
Available operators: +
(add), -
(subtract), *
(multiply), /
(divide), >
(greater than), >=
(greater than or equal), <
(less than), <=
(less than or equal), ==
(equals), !=
(not equals), !
(not), &&
(and), ||
(or), &
(bitwise and), |
(bitwise or), ^
(bitwise xor), >>
(right bitshift), <<
(left bitshift).
String operations
Recipes are not limited to numbers. If we have two fields first_name
and last_name
but want the field full_name
to be automatically calculated, we define the following recipe:
Note that we can also use single quotes instead:
Properties
Fields can not only be numbers or text, but also objects that have properties. Fields of type select
for example hold relations to other Brezel entities. Say we want to define a field total
that depends on the price of the selected product product
and another field quantity
. Then we can write the following recipe:
Subscript syntax works too in this case:
Functions
Often, we want to transform values in some way. There are pre-defined functions available for that, for example when we want to round numbers for a currency field:
Conditionals
Ternary operator
Sometimes we want the value to be something in one case, but be something different in another case. Then we can write:
If the condition
is true
, it will return x
, otherwise it will return y
. Example:
will return 0.07
if the category in question is Food, otherwise we get 0.19
.
Null-coalescing operator
If you just want the resulting expression if it does not evaluate to null
and another expression otherwise, you can use the null-coalescing operator:
This will return the value of specific_tax
if specific_tax
is not null
, otherwise it returns default_tax
.
List fields
Fields of type list
are expressed as arrays. Having a field positions
consisting of list entries with child fields product
, unit_price
and quantity
, we can express the sum position_total
of one single list entry to be:
Imagine then that we have the following positions, here illustrated in the form (product, position_total)
: (Donut, 4.50)
, (Pretzel, 2.80)
and (Bread, 6.00)
. Applying the following recipe:
returns 4.50
. But we can do more, because instead of specifying the index inside []
, writing something like…
will give us the following result:
This is called wildcard expression, because it maps each entry in the list to whatever is defined after .
. Here, each position in the list is mapped to position.position_total
.
If we now want to sum all position_total
fields of the positions
list, we can write
which gives us 13.30
.
Arrow functions
Some functions can also accept functions as input, which are defined in the form of (a, b, ..., c) => y
where a, b, ..., c)
are parameters andy
is the return value. This is especially useful when we want to filter a list by some criterium:
which yields [4, 5]
.
Math
sum
Signature
sum(items: list)
Description
Returns the sum of all items in the list.
Example
avg
Signature
avg(items: list)
Description
Returns the average of all items in the list.
Example
round
Signature
round(value: number, precision: number)
Description
Returns the value rounded to the specified precision.
Example
floor
Signature
floor(value: number, precision: number)
Description
Returns the value rounded down to the specified precision.
Example
ceil
Signature
ceil(value: number, precision: number)
Description
Returns the value rounded up to the specified precision.
Example
max
Signature
max(items: list)
Description
Returns the maximum of all items in the list.
Example
min
Signature
min(items: list)
Description
Returns the minimum of all items in the list.
Example
sin
Signature
sin(value: number, precision: number)
Description
Returns the sine of the value as a number between -1 and 1.
Example
cos
Signature
cos(value: number, precision: number)
Example
exp
Signature
exp(value: number, precision: number)
Example
pow
Signature
pow(value: number, exponent: number)
Example
sqrt
Signature
sqrt(value: number, precision: number)
Example
abs
Signature
abs(value: number)
Example
vector
Signature
vector(values: list)
Example
rand
Signature
rand(start: number, end: number)
Example
String
len
Signature
len(value: string)
Example
substr
Signature
substr(value: string, start: number, end: number)
Example
contains
Signature
contains(value: string, search: string)
Example
toUpperCase
Signature
toUpperCase(value: string)
Example
random.password(minLength, maxLength)
Signature
random.password(minLength: number, maxLength: number)
Example
Object
len
Signature
len(value: object)
Example
contains
Signature
contains(value: object, key: string)
Example
list
Signature
list(value: object)
Example
relation
Returns a new object with only the required keys for storing relations.
Signature
relation(value: object)
Example
join
Signature
join(glue: string, pieces: list)
Example
Date
today
Signature
today()
Example
now
Signature
now()
Example
date
Signature
date(value: string, timezone: string)
Example
duration
Signature
duration(value: string)
Example
User
user
-> User
Returns the current user from local store. The user gets updated on every refresh.
Signature
user()
Example
hasRole
Signature
hasRole(role: string)
Example
JSON
json.decode
Signature
json.decode(value: string)
Example
json.encode
Signature
json.encode(value: string)
Example
Regex
regex.quote
Signature
regex.quote(value: string, delimiter: string)
Example
regex.matchAll
Signature
regex.matchAll(pattern: string, subject: string)
Example
Misc
env
API
Signature
env(name: string)
Example
- Math functions:
sum
,avg
,round
,floor
,ceil
,max
,min
,sin
,cos
,exp
,pow
,sqrt
,abs
,vector
,rand
- String functions:
len
,substr
,contains
,toUpperCase
,random.password(minLength, maxLength)
- Object functions:
len
,contains
,list
,relation
,join
- Date functions:
today
,now
,date
,duration
- User functions:
user
,hasRole
- JSON functions:
json.decode
,json.encode
- Regex functions:
regex.quote(string, delimiter)
,regex.matchAll(pattern, subject)
- Misc functions:
env