improvement(tables): add per-column-type behavior registry - #6104
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview
CSV import fixes type drift: coercion targets use Reviewed by Cursor Bugbot for commit a15b7d4. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThe PR centralizes table column behavior while preserving existing behavior for all registered column types.
Confidence Score: 5/5The PR appears safe to merge with no actionable behavioral, build, data-integrity, or security defects identified. The registered column types retain their previous coercion, validation, compatibility, and SQL-cast behavior, while the CSV changes correctly feed select values into schema-level resolution and prevent whitespace-only numbers from becoming zero.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/table/column-types.ts | Introduces the six-type behavior registry and preserves the prior parsing, validation, SQL-cast, and conversion semantics for registered types. |
| apps/sim/lib/table/validation.ts | Replaces duplicated parsing and validation switches with registry delegation without changing behavior for supported schemas. |
| apps/sim/lib/table/columns/service.ts | Delegates type-conversion compatibility checks to behavior definitions equivalent to the removed switch branches. |
| apps/sim/lib/table/import.ts | Aligns CSV coercion types with supported column types, passes select text to schema-level resolution, and maps whitespace-only numeric cells to null. |
| apps/sim/lib/table/select-values.ts | Moves select option resolution and multi-select splitting into a shared pure helper module with equivalent behavior. |
| apps/sim/lib/table/sql.ts | Delegates numeric and timestamp SQL cast selection to the registry while preserving generated query behavior. |
| packages/testing/src/factories/table.factory.ts | Aligns testing fixtures with the production column-type union by supporting select columns. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Input[Raw cell value] --> Registry[Column type registry]
Registry --> Parse[Parse and coerce]
Registry --> Validate[Validate stored value]
Registry --> Format[Format display value]
Registry --> Compatible[Check type conversion]
Registry --> Cast[Select SQL cast]
Parse --> Persist[Row persistence]
Validate --> Persist
Compatible --> Migration[Column type migration]
Cast --> Query[Filter and sort query]
Reviews (1): Last reviewed commit: "fix(testing): add missing select type to..." | Re-trigger Greptile
Each column type's SQL cast, parse, validate, format, and conversion- compatibility rules were implemented as independent switch statements scattered across sql.ts, validation.ts, and columns/service.ts. Adding a type meant hand-updating every switch, and a missed one failed silently and differently depending which switch it was. column-types.ts is the single per-type definition those switches will delegate to, keyed by a Record typed against COLUMN_TYPES so a missing entry is a compile error instead of a runtime surprise. select-values.ts gains resolveSelectOptionId/splitMultiSelectInput (moved here rather than importing validation.ts, which pulls in @sim/db and would taint or cycle with this otherwise-pure module) so the registry's select behavior has a shared, pure home to depend on. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
jsonbCastForType's switch is replaced by a delegate to the new registry's sqlCastForColumnType, so a new column type's sort/filter cast only needs to be declared once, in column-types.ts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…istry coerceValueToColumnType and validateRowAgainstSchema's switches are replaced by delegates to the registry's parse/isValidValue, so a new column type's coercion and shape-check rules only need to be declared once. The now-dead optionIds helper is removed, and resolveSelectOptionId/splitMultiSelectInput move to select-values.ts (their tests move with them) now that the registry depends on them living there instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… registry isValueCompatibleWithType's switch — the gate updateColumnType checks before committing a column's type change — is replaced by a delegate to the registry's isValueCompatibleWithColumnType, so a new column type's conversion rules only need to be declared once. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tespace bug CsvColumnType was a hand-duplicated, narrower copy of COLUMN_TYPES and had silently drifted to exclude 'select' — papered over at its one call site with an unsafe `as CsvColumnType` cast. Split it into two honestly-scoped types: ColumnType (= COLUMN_TYPES, what a CSV cell's target column can actually be) and InferableColumnType (the 4 types inferColumnType can actually guess from raw text, declared independently so it can't silently inherit types it was never taught to detect). Also fixes a real divergence found in the process: coerceValue's number case ran Number(value) without guarding whitespace-only input first, so a blank CSV cell imported as 0 instead of null. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TableColumnType had also drifted out of sync with COLUMN_TYPES, missing 'select'. It can't import COLUMN_TYPES to derive itself (packages/* can't import apps/*), so it stays hand-maintained — documented in place so the next drift is at least explained. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
cefc034 to
a15b7d4
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a15b7d4. Configure here.
| * column type" and "every type we can guess from raw text" are different, | ||
| * independently-sized questions. See `InferableColumnType`. | ||
| */ | ||
| export type ColumnType = (typeof COLUMN_TYPES)[number] |
There was a problem hiding this comment.
Duplicate ColumnType barrel export
Medium Severity
The new ColumnType export in import.ts duplicates an existing ColumnType alias already available from types.ts (via ColumnDefinition['type']). This redundancy causes a name collision when both are re-exported from the barrel, leading to an ambiguous export.
Reviewed by Cursor Bugbot for commit a15b7d4. Configure here.


Summary
column-types.ts) so each of the 6 column types' SQL cast, parse, validate, format, and conversion-compatibility rules live in one place instead of ~10 scattered switch statements acrosssql.ts,validation.ts, andcolumns/service.tsselect-values.tsCsvColumnTypetype drift (was missingselect) by splitting it intoColumnType(coercion target) andInferableColumnType(CSV type-inference output); fix a bug where a whitespace-only CSV number cell imported as0instead ofnullselectdrift in the test-fixture factory (packages/testing)Type of Change
Testing
bun run type-check(sim, @sim/testing) — cleanbun run lint— cleancheck:*audits — cleanlib/tablesuite: 536 passing (was 486 before this PR; +50 new — 48 directcolumn-types.tstests, 2 for the CSV whitespace fix)@sim/testingsuite: 39 passingChecklist