with one click
runtime-formulas
// Create or update Baserow runtime formulas in `core/formula/runtime_formula_types.py`. Use when adding or updating a runtime formula.
// Create or update Baserow runtime formulas in `core/formula/runtime_formula_types.py`. Use when adding or updating a runtime formula.
Add or update a Baserow Application Builder element type across backend models, backend ElementType registration, frontend element registry/components/forms/icons/translations, migrations, and targeted tests. Use when creating or changing an element shown in the builder add-element modal, page preview, public page rendering, form elements, collection elements, container elements, or enterprise-only builder elements.
Create or update a Baserow in-app notification for an event. Use when adding a backend `NotificationType`, wiring frontend notification rendering and routing, defining the notification target, or preventing duplicate notifications for the same event object.
Create or update Baserow integration and service types, including services exposed as Application Builder data sources, Builder workflow actions, Automation node actions, Automation node triggers, or dashboard data sources. Use when adding a ServiceType/IntegrationType subclass, registering backend/frontend types, or wiring service wrappers in builder or automation.
Manage Baserow backend feature layers across Django models, handlers, services, undoable actions, serializers, API views, URLs, permissions, signals, migrations, and tests. Use when adding or changing backend CRUD/domain behavior that spans model, handler, service, action, and view layers; use the automation modules as the preferred modern pattern.
Create, edit, or debug Baserow permission operations and permission managers across backend and frontend, including OperationType, PermissionManagerType, PERMISSION_MANAGERS ordering, frontend permission managers, and permission tests.
Explain, debug, or extend Baserow runtime formulas, including FormulaField/JSONFormulaField storage, FormulaSerializerField validation, runtime formula functions, backend and frontend data providers, formula context dispatch data, import/export path rewriting, and tests.
| name | Runtime Formulas |
| description | Create or update Baserow runtime formulas in `core/formula/runtime_formula_types.py`. Use when adding or updating a runtime formula. |
| version | 1.0.0 |
Use this skill when a task involves creating or updating a Baserow runtime formula.
Runtime formulas are used in the Application builder, Automation builder, and the AIField in the Database builder. Any changes made to runtime formulas must be compatible with all three parts of the codebase.
The runtime formulas need to be implemented in both the backend and the frontend. In the backend, the runtime formulas are evaluated at runtime. In the frontend, the corresponding runtime formulas are used to validate correct syntax.
This repo already has the core patterns. Prefer copying an existing implementation close to the target behavior, and then modifying it to support the new requirements, instead of inventing a new structure.
Before adding a new runtime formula type, identify whether a new argument type is needed.
Note that both the backend and frontend define parse_args() and parseArgs() respectively, which uses the argument type's parse() to transform arguments before they are executed.
There are some additional methods that control how the formula is rendered in the rich text formula editor, but most simple formulas shouldn't need to override them:
toNode()formulaComponentType()formulaComponent()fromNodeToFormula()Ensurers are reusable normalization/coercion functions that convert an arbitrary value into a specific type, or raise an error if conversion is not possible. They live in:
backend/src/baserow/core/formula/validator.pyweb-frontend/modules/core/utils/validator.jsExisting ensurers include ensure_string, ensure_duration, etc.
Argument types should delegate their test() and parse() methods to an ensurer rather than implementing inline conversion logic.
test(), call the ensurer inside a try/except (backend) or try/catch (frontend) and return True/False.parse(), return the ensurer's result directly.Runtime formula types should use ensurers in their execute() method when converting input values, rather than calling low-level conversion functions (e.g. datetime.strptime(), moment()) directly.
Before creating a new ensurer, check whether an existing one already covers the target type. Only create a new ensurer when no existing one handles the conversion.
When introducing a new data type (e.g. timedelta / Timedelta), the existing ensure_string() and ensure_integer() ensurers may need to be updated to handle coercion of the new type into strings and integers.
For example:
ensure_string() was updated to convert timedelta to a human-readable string like "1 day"ensure_integer() was updated to convert timedelta to total seconds.django.core.exceptions.ValidationError on failure.TypeError or Error on failure.backend/tests/baserow/core/formula/test_validator.pyweb-frontend/test/unit/core/utils/validator.spec.jsUseful backend files:
backend/src/baserow/core/formula/runtime_formula_types.pybackend/src/baserow/core/formula/argument_types.pybackend/src/baserow/core/apps.pybackend/tests/baserow/core/formula/test_runtime_formula_types.pyA new runtime formula type should subclass RuntimeFormulaFunction and implement the following properties and methods.
typeThis is a unique lower-cased and snake-cased identifier.
argsThis is a list of argument types.
If the argument type or length are dynamic or optional, min_args, validate_type_of_args(), and validate_number_of_args() will likely also need to be implemented.
As a general rule, prefer to use a more permissive argument type when possible. E.g. RuntimeConcat allows 2 or more arguments. Each argument is coerced to a string. This allows concat() to concatenate a mix of ints, floats, and strings to produce a result.
execute()This method should compute and return the expected result for the runtime formula type.
The runtime formula argument type defines the acceptable arguments for a runtime formula types. The most permissive argument type is AnyBaserowRuntimeFormulaArgumentType, which will accept any argument type, such as int, string, etc.
When creating a new runtime formula type, consider whether a new argument type is necessary or whether an existing argument type is already available that satisfies the requirements.
Note that the constructor can accept kwargs, such as cast_to_int for NumberBaserowRuntimeFormulaType. E.g. RuntimeRound uses optional=True, cast_to_int=True.
All argument types must implement both test() and parse(). The get_error_message() method is special, which is described next.
Argument types should delegate to an ensurer in validator.py for their test() and parse() implementations. For example, DurationBaserowRuntimeFormulaArgumentType delegates to ensure_duration(). Avoid duplicating conversion logic inline when an ensurer exists or can be created.
get_error_message()When an argument type can return a useful human-readable error message, this method should be overridden to return an error message.
E.g. the TimezoneBaserowRuntimeFormulaArgumentType argument type overrides get_error_message() to return a human-readable error message when the timezone value is invalid.
After creating a new runtime formula type, it must be imported and registered in backend/src/baserow/core/apps.py.
The syntax is: formula_runtime_function_registry.register(RuntimeFoo())
For new runtime formula types, tests should be added in test_runtime_formula_types.py. Notice that existing tests ensure that:
execute() method returns the expected result.validate_type_of_args() correctly validates various possible inputs, and either returns None to indicate that the argument is allowed, or returns the same argument back to indicate it is an invalid argument.validate_number_of_args() method returns a bool where True indicates the number of arguments are valid, and False otherwise.get_error_message() is overridden:
test_argument_types.py.test_runtime_formula_types.py.The frontend needs a parallel implementation of the backend changes in order to support validating the syntax of the runtime formula.
Useful frontend files:
web-frontend/modules/core/runtimeFormulaTypes.jsweb-frontend/modules/core/runtimeFormulaArgumentTypes.jsweb-frontend/modules/core/plugin.jsweb-frontend/test/unit/core/formula/runtimeFormulaTypes.spec.jsweb-frontend/locales/en.jsonweb-frontend/modules/core/utils/web-frontend/modules/core/enums.jsA new runtime formula type should extend the RuntimeFormulaFunction class. It should implement the following methods.
getType()This corresponds to the backend's RuntimeFormulaFunction's type property and should be an exact match.
getFormulaType()This defines the formula type as an enum. Possible choices are FORMULA_TYPE.FUNCTION if the runtime formula type is a function like concat(), or FORMULA_TYPE.OPERATOR if it is an operator such as =, +, etc.
getCategoryType()This defines how the runtime formula type is categorized and grouped in the frontend. Pick one of the enum options in FORMULA_CATEGORY.
execute()The execute() method should return the desired result of the runtime formula being called. The behaviour should be identical to the backend's corresponding execute() implementation.
args getterThis getter property corresponds to the backend's args property. It should return an array of argument types.
If the argument type or length are dynamic or optional, numArgs(), validateArgs(), and validateNumberOfArgs() will likely also need to be implemented.
As a general rule, prefer to use a more permissive argument type when possible. E.g. RuntimeConcat allows 2 or more arguments. Each argument is coerced to a string. This allows concat() to concatenate a mix of ints, floats, and strings to produce a result.
validateNumberOfArgs()This corresponds to the backend's validate_number_of_args() method and should implement the same behaviour.
validateArgs()This is a higher level method that internally calls validateTypeOfArgs() (corresponds to the backend's validate_type_of_args() method). It can be overridden for custom validation logic. It should implement the same behaviour as the backend logic.
An important point to note is that in the validation visitor, there will be additional context that can provide additional context to help with validation. This is not available to the execution visitor.
getOperatorSymbol getterThis getter property should only be implemented when the getFormulaType() returns an operator. It should return a operator symbol, e.g. +, -, >=, etc.
getDescription()This should return a description of the runtime formula type. The description should be added to
the runtimeFormulaTypes dict in web-frontend/locales/en.json.
getExamples()This should return an array of objects. Each object should define the formula and result keys. The formula value should be and example of how to use the runtime formula, and the result value should show an example of the expected result of calling the runtime formula.
Similar to the corresponding backend implementation, the runtime formula argument type defines the acceptable arguments for a runtime formula types and are defined in web-frontend/modules/core/runtimeFormulaArgumentTypes.js.
The most permissive argument type is AnyBaserowRuntimeFormulaArgumentType, which will accept any argument type, such as int, string, etc.
When creating a new runtime formula type, consider whether a new argument type is necessary or whether an existing argument type is already available that satisfies the requirements. If a new type is created for the backend, the frontend will likely also need a new type.
All argument types must implement both test() and parse(). The getErrorMessage() method is special, which is described next.
getErrorMessage()When an argument type can return a useful human-readable error message, this method should be overridden with a key defined in the runtimeFormulaTypeErrors translation key.
E.g. the TimezoneBaserowRuntimeFormulaArgumentType argument type overrides getErrorMessage() to return a human-readable error message when the timezone value is invalid.
After creating a new runtime formula type, it must be imported and registered in web-frontend/modules/core/plugin.js.
Add the new runtime formula to the fns array.
For new runtime formula types, tests should be added in runtimeFormulaTypes.spec.js. Notice that existing tests ensure that:
describe() scope.execute(), validateTypeOfArgs(), and validateNumberOfArgs() are tested with parameterized tests, similar to the corresponding backend tests.getErrorMessage() is overridden:
runtimeFormulaArgumentTypes.spec.js.runtimeFormulaTypes.spec.js.When creating a new runtime formula type, both the backend and frontend will need parallel implementations:
backend/src/baserow/core/formula/runtime_formula_types.pyweb-frontend/modules/core/runtimeFormulaTypes.jsbackend/src/baserow/core/formula/argument_types.pyweb-frontend/modules/core/runtimeFormulaArgumentTypes.jsexecute() method requires type coercion that isn't covered by an existing ensurer.
backend/src/baserow/core/formula/validator.pyweb-frontend/modules/core/utils/validator.jsensure_string(), etc) need updating to handle coercion of the new type.backend/tests/baserow/core/formula/test_validator.pyweb-frontend/test/unit/core/utils/validator.spec.jsbackend/src/baserow/core/apps.pyweb-frontend/modules/core/plugin.jsbackend/tests/baserow/core/formula/test_runtime_formula_types.pyweb-frontend/test/unit/core/formula/runtimeFormulaTypes.spec.jsThe frontend will additionally need translations for the description: web-frontend/locales/en.json.
When updating an existing runtime formula type, ensure that both the backend and frontend have:
Do not add a new runtime formula type or an argument type, without first checking that an existing formula type or argument type already provides similar functionality.
If an existing type can be minimally refactored to support the new requirements, suggest a refactor.