| title | Expression |
|---|---|
| description | Expression protocol schemas |
{/*
Canonical wire format for all "expression"-shaped metadata across ObjectStack (formula fields, predicates, conditions, criteria, visibility rules, seed dynamic values, …).
The persisted form is { dialect, source } (and, after objectstack compile normalization, { dialect, ast }). String-only shorthand is
accepted at input time for developer ergonomics; build emits the canonical
envelope.
| dialect | engine | use |
|---|---|---|
cel |
@objectstack/formula (cel-js + ObjectStack stdlib) |
formulas, predicates, seed dynamic values |
cron |
none at parse time — croner fires it at schedule time, on the one wired slot |
job schedules |
template |
placeholder interpolation at evaluate time (same variable scope as CEL); canonically {{var}}, but the accepted spelling belongs to the renderer, not to this schema — see TemplateExpressionInputSchema |
notification subjects/bodies, titleFormat, prompt templates |
No cron syntax is judged at parse time: croner evaluates a cron slot only
when CronSchedule.expression is scheduled (toBoundaryJobSchedule →
CronJobAdapter, where an invalid pattern is refused); every other
cron-typed slot is parsed and reaches no engine, and @objectstack/formula's
registered cron engine has no caller outside that package.
A TYPED slot — one declared with CronExpressionInputSchema or
TemplateExpressionInputSchema — takes a bare, non-blank string (shorthand
for its own dialect) or an envelope declaring that one dialect. An envelope
naming any other dialect, and a blank string, are refused at the slot with
one issue whose message names the dialect and the fix. Only the untyped
ExpressionInputSchema takes every declared dialect in envelope form.
Those three are the whole list — it is exactly the ExpressionDialect enum
below. Procedural JavaScript is not a dialect: it is the L2 authoring
surface, the sandboxed, capability-gated ScriptBody { language: 'js' } in
hook/action bodies. A js row stood in this table long after the dialect was
retired in #3278 (ADR-0058 addendum); ExpressionSchema rejects
dialect: 'js'.
SQL fragments (analytics joins, partial indexes) are intentionally not routed through this schema — they stay driver-native because their security posture and portability story differ.
See also: content/docs/concepts/north-star.mdx §8 "No private expression DSL"
**Source:** `packages/spec/src/shared/expression.zod.ts`import { CronExpressionInputSchema, EvaluatedExpressionSchema, EvaluatedExpressionInputSchema, ExpressionSchema, ExpressionDialect, ExpressionInputSchema, ExpressionMetaSchema, PredicateSchema, PredicateInputSchema, TemplateExpressionInputSchema } from '@objectstack/spec/shared';
import type { CronExpressionInput, EvaluatedExpression, EvaluatedExpressionInput, Expression, ExpressionDialect, ExpressionInput, ExpressionMeta, Predicate, PredicateInput, TemplateExpressionInput } from '@objectstack/spec/shared';
// Validate data
const result = CronExpressionInputSchema.parse(data);This schema accepts one of the following structures:
Type: string
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | 'cron' |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
✅ | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
This schema accepts one of the following structures:
Type: string
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
✅ | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
celcrontemplate
This schema accepts one of the following structures:
Type: string
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
| Property | Type | Required | Description |
|---|---|---|---|
| rationale | string |
optional | |
| generatedBy | string |
optional |
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
This schema accepts one of the following structures:
Type: string
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | Enum<'cel' | 'cron' | 'template'> |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |
This schema accepts one of the following structures:
Type: string
| Property | Type | Required | Description |
|---|---|---|---|
| dialect | 'template' |
✅ | |
| source | string |
optional | |
| ast | any |
optional | |
| meta | { rationale?: string; generatedBy?: string } |
optional |