v0.14.0 — Computed fields in the schema
v0.14.0 — Computed fields in the schema
Minor release: a new opt-in schema field type, computed, lets a value be derived from other fields at render time instead of being maintained by hand and stored in the payload.
What this fixes
Before this release, derived quantities (budget variance = plan minus actual, days left, percentage complete, risk score) had to be kept as plain number fields. Users updated them by hand whenever one of the inputs changed, and they drifted the moment anyone forgot. The new type: 'computed' field replaces those values with a function the schema declares:
{ key: 'variance', label: 'Budget variance', type: 'computed',
compute: (r) => r.plan - r.actual }The result is rendered in the table, the read-only form field, the detail view, the CSV export, and any metric tile that aggregates it. Sorting and validation rules that reference the field work the same as for stored number fields.
Decisions
- Why a function and not an expression string: the schema is already plain JS, the rest of the field definitions are functions (
validate,transform), and a function gives field authors the full language for what they need (arithmetic, ternaries, calls into small pure helpers). An expression mini-language would have added parser surface area for a feature that does not need it. - Memoised per render pass, not globally: the value is recomputed when the schema author asks for a different one (e.g. after editing a value), and is cached for the lifetime of that render. A single user-visible change is one recomputation, not N. A 1,000-record smoke run stays well under the 500 ms wall-clock budget the issue asked for.
- Errors never crash the app: if
compute(record)throws, the cell renders as a dash (—) and the console receives exactly one warning per(singular, fieldName, recordId, errorMessage)tuple. A second failure of the same tuple in the same render is deduplicated — you get the signal without the spam. validateMetricsnow acceptssum(computed)andavg(computed)as well as the stored-field forms it already accepted. The catalogue stays closed: onlycount,sum,avgremain, andsum/avgare gated to numeric sources (which now includescomputedreturning a number). No new metric kind.- Backwards compatible at every surface: schemas that do not declare any
computedfield behave identically to v0.13.x. The portfolio demo gained aBudget lefttile (sum(variance)) so the feature is visible without reading the docs.
For existing users
- Stored
numberfields still behave as before. The change is additive:validateMetricsaccepts one more source type,computeis a new key you may add to your schema, and the renderer handles the new field type. Existing schemas need no edits and produce the same output. - CSV export now contains the computed column when the field is in the visible columns. If your downstream tooling imports the CSV and expects only stored columns, you may want to hide the computed column from the export until downstream is ready.
- Validation rules can reference a computed field the same way they reference a stored one. If a rule fires on a
computedfield whose formula threw, the rule seesundefinedand the cell renders as—; the rule is not silently skipped. - The form renderer treats a stored
0as0(previously it showed—). This is a tiny visual fix from OPEN-79 / PR #51 that v0.14.0 picks up; no value change in saved data. npm testnow runs eight suites locally (the newdomain-swap-crashsuite is part of the standard run since v0.13.1).
Consciously not included
- No cross-record computations. A
computefunction receives one record at a time; totals across the record set belong to themetricsblock, not to the field. This is the same boundary the closedmetricscatalogue already enforces. - No computed-of-computed chains. A
computedfield can read stored fields and othercomputedfields, but only by name, not as a reactive subscription. If the underlying record changes between renders, the cache key (recordidentity) invalidates the memo. - No persistent cache. Computed values are never written to the data block. Saving the file is byte-identical to the saved state of a schema without
computedfields. This is the property that makes the feature safe to add to long-lived schemas. - No import path. A computed field cannot be supplied through CSV/JSON import; the importer rejects unknown keys and ignores computed keys in payloads. Imported records compute the value on the next render, like locally edited records.
- No AI write path. The AI integration can read computed values (so it can answer questions like "what is the total budget variance?") but cannot write to a
computedfield; the field is read-only in the form and absent from the AI's allowed-keys list.
Wiki: https://github.com/m-dohmen/openToolbox/wiki/Computed-Felder
Full changelog: v0.13.1...v0.14.0
