Database V2 overhaul - #31
Conversation
Everything-is-a-node model from exploration 0159: - DatabaseField, DatabaseSelectOption, DatabaseView node schemas - json() property builder for structured config values - Database/DatabaseRow bumped to @2.0.0 - field-operations: field CRUD + select options as nodes (concurrent option creation merges cleanly), fractional-index ordering - view-node-operations: view CRUD with per-view layout overrides - setupDatabase() replaces Y.Doc-based initialization Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
createNodeDatabaseSchemaResolver reads DatabaseField nodes and the Database node's new schemaVersion property instead of the Y.Doc data map. fieldsToStoredColumns adapts field nodes to the StoredColumn shape consumed by the pure clone/template transforms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure-TS foundation for the V2 database grid (exploration 0159): - GridState reducer: cell/range/row/column/all selection, Sheets-style cursor semantics, editing lifecycle (edit/replace modes), peek, resize clamping - Keymap: full 0159 keyboard map (arrows/extend/jump, Home/End, Tab, Enter/F2/type-to-replace, clipboard, fill-down, undo/redo, comment, insert-row, quick-find) in browsing and editing modes - Clipboard: Excel-style TSV serialize/parse + per-field-type paste coercion with unresolved-option reporting for inline tag creation 78 unit tests covering every transition and shortcut. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
React layer over the grid engine: - GridSurface: TanStack Virtual rows, full keymap wiring, TSV copy/cut/paste with typed coercion + inline option creation on paste, fill-down, dnd-kit row reorder via gutter handles, ARIA grid roles - GridHeader: sort toggle, dnd-kit column reorder, pointer resize, field menu + add-field hooks - GridCell: property-handler rendering, draft-first inline editors with replace-mode seeding, presence rings + name flags, comment badges Store-agnostic: data in via GridField/GridRowData, mutations out via GridCallbacks, so view nodes stay the single source of truth. 22 component tests across click/keyboard/clipboard/structure paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fields, views, select options, and rows all read through useQuery (DataBridge → SQLite) with materialized-view caching and FTS search. View nodes are the single source of truth — no mirrored React state. - per-view layout: fieldOrder/fieldWidths/hiddenFields overrides - view pipeline: fractional-order base window → filter/sort engines - mutations: cells, rows (fractional drop positioning), fields, typeahead option creation with case-insensitive dedupe, view sort-cycle/filters/group - append bursts stay ordered via synchronously-bumped sort-key tails - scoped local-only undo via useUndoScope over the database's nodes SelectOption nodes gained a denormalized database relation so a whole database's options load in one indexed query. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ty, quick-find View tabs over View nodes, sort chips with toggle/clear, FilterBuilder popover behind data↔surface filter-dialect adapters (the surface dialect retires with the legacy table path), group-by selector, field-visibility popover, and the quick-find box that feeds useGridDatabase's FTS search. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Select editor rebuilt as a combobox (typeahead filter, keyboard-only flow, clear entry, picker-select commits). Both select and multiSelect editors persist new options through config.onCreateOption — wired from GridSurface via GridCell so created tags become DatabaseSelectOption nodes and cells store real node IDs. Named SelectColor values render through a soft Notion-style chip palette. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The web database shell is now a thin composition: - useGridDatabase drives GridToolbar + GridSurface + GridPeek - the Database Y.Doc serves only as the awareness channel (cell focus presence rings + name flags) - cell comments anchor through useDatabaseComments: badges/counts in the grid, CommentPopover for existing threads, inline composer (and Cmd/Ctrl+Shift+M) to start one - row peek side panel with stacked live editors - field menu (rename/type/hide/delete) and add-field popovers - fresh databases bootstrap a title field + table view through the hook Deletes the TanStack-Table-era shell (two ViewConfig dialects, Y.Doc column bootstrap, lossy filter translation). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same thin shell as web (useGridDatabase + GridToolbar/GridSurface/ GridPeek + awareness presence + anchored comments), preserving minimalChrome for embedded canvas previews. Replaces the 2000-line dual-undo-domain (Y.UndoManager + structured) implementation — V2 mutations are all node ops, so the grid's single scoped undo covers everything. Canvas-shell fixture updated to the Database@2.0.0 IRI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greenfield demolition from exploration 0159: - legacy-model.ts (624 lines) and legacy-migration.ts removed outright, with their tests and every export - useDatabase/useDatabaseDoc stripped to the canonical node/Y.Doc paths (no storage-mode branching, no migration API) - relation editor + RowPickerModal ported to useGridDatabase, resolving row titles through V2 title fields - document-model detection reduced to canonical|empty and relocated to database-doc.ts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…base e2e on V2 The node-sync wire format dropped protocolVersion — a hashed field — so every relayed change failed verifyChangeHash at the hub and browser-to-browser node sync silently never converged. Serializer and deserializer now carry it (the hub side already did); regression test added. Grid fixes surfaced by real-browser e2e: - type-to-replace seeds initialize synchronously (an effect ran after the editor captured its initial value, dropping the first character) - text-like editors take autoSelect=false for seeded sessions (caret at end instead of select-all, which let the next keystroke replace the seed) - one commit per edit session in GridCell (the unmounting editor's blur re-committed a stale draft, clobbering picker-select values with null) - focus reclaim after editing moved to an effect so the editor renders closed before its blur fires - pickers stop Enter propagation so the grid doesn't close the session mid option-create E2E harness rebuilt on useGridDatabase + GridSurface/GridToolbar with shared spawn helpers; specs rewritten for V2 (7 passing in chromium, including two-user hub convergence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
File cells are fully functional:
- cell FileRef unified with the blob-layer shape ({cid, name,
mimeType, size}) — content-addressed, resolved to URLs through the
BlobService (greenfield: old {id,url} shape removed)
- file property handler rebuilt: upload button + drag-drop in the
editor, remove/replace, paperclip chips with size, inline image
thumbnails via a cached CID→URL resolver
- GridSurface: dropping a file onto a (non-editing) file cell uploads
and writes the FileRef directly
- GridPeek: inline image previews per file field and a full-screen
lightbox
- both app shells wire BlobService upload/getUrl into the grid and
peek (callbacks stay store-agnostic via config, like option create)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…perf budgets - GridToolbar gains an overflow menu: Export CSV, Export JSON, Import CSV (callbacks stay app-owned; engines live in @xnetjs/data, now exported from the package root) - both shells implement export (current view rows/fields) and CSV import: header fields created with inferred types, select/multiSelect values persisted as SelectOption nodes and mapped to IDs, rows added through the grid hook - useGridDatabase populates created/createdBy/updated auto fields from node metadata - local appends use deterministic (jitter-free) sort keys — appends chain off the local tail, so jitter only risked rare misordering - perf budget tests: 10k rows render a bounded virtualized DOM within budget, cursor traversal budget, 100k reducer ops under 500ms Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DatabaseScreen renders rows as cards (title + a three-field summary) backed by the same useGridDatabase hook as the desktop grid, so edits sync and undo identically. Tapping a card opens a full-screen row editor with stacked native controls: text/number/date inputs, checkbox switch, select/multiSelect chips with inline typeahead tag creation (SelectOption nodes); computed/rich types render read-only. Add-row FAB opens the new row for editing. Home gains database create/list. Implemented as a native screen (React Native cannot render the DOM grid); the views registry mobile flag stays available for web-tablet surfaces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- FormulaService (AST + value caches) wired into useGridDatabase's row
pipeline: formula fields compute from the row's other cells before
filters/sorts run, and recompute when dependencies change
- computed/auto fields (formula, rollup, created/updated/by) are
non-editable in the grid — startEdit is a no-op on them
- field menus gain a formula expression editor ({{fieldId}} refs,
persisted to field config); formula joins the creatable field types
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nd type conversion The grid keeps its typed-column model but types like a spreadsheet: - ghost row: an empty row below the data; typing in any cell creates a row with that value (plus-sign gutter, arrow-navigable, empty commits are no-ops) - ghost column: an empty column on the right; typing creates a new text field and sets that row's cell - smart retyping: changeFieldType converts existing values through the new convert-cell engine — comma-separated text becomes multiSelect tags (options persisted as SelectOption nodes), numeric/currency/ percent strings become numbers, truthy text becomes checkboxes, dates parse, option IDs stringify back to names; unconvertible values clear rather than corrupt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…polish pass - rollups compute in useGridDatabase: related rows fetched through the store (cross-database), aggregated per row with the rollup engine, merged into the row pipeline without effect loops - shared FieldConfigEditor in the field menus: relation target-database picker, rollup relation/target-field/aggregation pickers (target fields queried from the related database), formula expression editor (deduplicates the per-shell textarea) - polish: tooltips with shortcut hints across toolbar/header/footer, empty-state hint over the ghost row, GridSkeleton loading placeholder replacing the loading text in both shells, long-press TouchSensor for column/row drag on touch devices Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…reload The two-user spec now proves the collaboration story end to end: - presence: user 2's cell focus renders a colored ring + name flag on user 1's grid (harness wires the awareness channel like the shells) - undo isolation: user 1's undo reverts only their own cell edit; user 2's concurrent typeahead-created tag survives - column resize: drag persists a per-view width override on the View node and survives a full page reload with in-memory storage — the width comes back through hub node-relay replay Plus pageerror capture in E2E_DEBUG and the handle-sizing CSS the harness shim was missing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Eight interactive stories under Core/Database/Grid V2, all running the real components against a small in-memory database (the surface is store-agnostic, so every interaction works in isolation): - Playground: full kit — toolbar, keyboard editing, sorting, filters, column drag/resize, row peek - Spreadsheet ghost cells: type in the empty row/column to create rows and fields - Typeahead tags: create flow minting colored options - Presence: remote cell-focus rings with name flags - Comment badges: per-cell anchored counts - Files and images: paperclip chips, inline thumbnails (data-URL SVG, no network), peek lightbox - Read-only and loading-skeleton states Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he query Three fixes for the typeahead experience: - the cell's overflow-hidden clipped the options dropdown entirely (it renders below the input, inside the cell) — clipping is now browsing-only, and the editing cell gets z-30 - editing rows paint above later absolutely-positioned sibling rows, which otherwise covered the dropdown - type-to-replace on select/multiSelect cells dropped the first typed character; it now seeds the autocomplete query via config (initialQuery), so typing 'd' opens the list pre-filtered jsdom missed all three (visibility and stacking aren't asserted); verified visually in Storybook, with regression tests for the autocomplete listing and query seeding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- shared GridFieldMenu component (rename, change type, hide, delete, config slot) — wired into the story harness, whose header ⋯ button previously had no handler at all; the button now hides when nothing is wired to it - FilterBuilder empty state was a single small link that read as a blank popover — it now shows an explicit 'No filters yet' panel; new filters default to a value-less operator (isNotEmpty) so adding one never blanks the table while the value is still being chosen - story type changes run the real convertCellValue engine (retype Task to multiSelect and comma values become tags, live in the demo) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ontract Commenting on cells was effectively unreachable: the badge only renders once a comment exists, and the sole creation entry point was Cmd/Ctrl+Shift+M — which Chrome reserves on macOS, so the page never sees it. Three fixes: - focused, commentless cells now show a visible add-comment affordance (the badge covers commented cells); keyboard shortcut still works where the browser allows it - the keyboard path now anchors the popover to the focused cell's element instead of passing null (shells fell back to screen-center) - integration test for the full data flow (comment on cell → badge count → thread retrieval → reply → resolve; row/column anchors index separately) and a browser e2e proving the anchor contract: the badge follows its row through sort changes because anchors encode rowId:fieldId, not coordinates — the harness now wires useDatabaseComments like the shells Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ear down sessions Toggling a checkbox was impossible: double-click opened the editor, but clicking the checkbox inside bubbled mousedown to the cell, re-entered grid selection, and tore the session down before the toggle landed. - checkbox cells now toggle in place on double-click and Enter — no edit session at all (Sheets/Notion behavior); readOnly and computed guards apply - the general class of bug is fixed too: the editor overlay stops mousedown/dblclick propagation, so clicks inside any editor (date pickers, file buttons, caret positioning) never re-dispatch grid selection mid-session Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add graphify skill instructions and Codex integration guidance - Commit generated graph report, raw graph data, and aggregated HTML visualization - Ignore local graphify runtime metadata and absolute-path hook state
- Move graph refresh from post-commit to pre-commit so graph artifacts land in the same commit - Add partial-staging protection before rebuilding graphify outputs - Regenerate and stage graph.json, GRAPH_REPORT.md, and aggregated graph.html during the hook
- Raise Workbox's precache limit from 3 MiB to 5 MiB. - Keep graphify outputs current after the web build config change.
|
Warning Review limit reached
More reviews will be available in 31 minutes and 37 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (114)
📝 WalkthroughWalkthroughThe PR adds a V2 database/grid stack, rewires web/electron/expo surfaces to it, and updates Graphify skill, hooks, and documentation. It also changes file references, sync payloads, and several UI property editors and tests. ChangesDatabase V2 grid stack
Graphify tooling and workflow docs
Sequence Diagram(s)sequenceDiagram
participant useGridDatabase
participant GridSurface
participant GridToolbar
participant DatabaseView
useGridDatabase->>DatabaseView: provide rows, fields, views, actions
DatabaseView->>GridToolbar: pass filters, sorts, search, export/import handlers
DatabaseView->>GridSurface: pass grid data and mutation callbacks
GridToolbar->>useGridDatabase: update view state and query filters
GridSurface->>useGridDatabase: update cells, rows, and fields
Estimated code review effort🎯 5 (Critical) | ⏱️ ~90+ minutes Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
|
Preview removed for PR #31. |
Summary
Validation
git push -u origin database-v2-overhaulran the pre-push hook successfully.445test files passed,6231tests passed,3skipped.Summary by CodeRabbit
New Features
Improvements
Documentation