Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra DataGrid Server-driven data grid for Laravel
Release notes
Changelog
Elyra

Changelog

All notable changes to Elyra DataGrid are documented here.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Packages are versioned together and released from git tags. A single tag (e.g. v0.1.3) publishes all four Composer packages — elyra/datagrid-protocol, elyra/datagrid-server, elyra/datagrid-livewire, and elyra/datagrid-js.

0.2.1 - 2026-07-21

Added

  • Natural-language filtering in the Vue and Svelte clients. Pass an ask function in the grid options (typically POSTing to an endpoint that calls GridDefinition::ask()) and both clients render an "ask" box in the toolbar. Submitting calls the new grid.askFilter() on the client core, which applies the returned filter and refetches, tracking asking / askError state. Omit ask to hide the box. New Messages keys askPlaceholder / ask / askFailed. Verified end-to-end in the Vue starter.

Fixed

  • Inter-package version constraints. Sibling packages required each other at ^0.1.0, which excludes 0.2.x and broke composer require/update on the 0.2 line. They now use >=0.1.0 <1.0.0, so the lock-stepped 0.x packages always resolve together across minor bumps.

0.2.0 - 2026-07-21

Added

  • Natural-language filtering ("ask the grid"). Users can type a question ("revenue over 50k in region Nord last quarter") and the grid translates it, server-side, into a FilterGroup via an LLM whose JSON-schema output is restricted to the grid's own declared columns and operators.
    • Safe by design: the result is re-validated against the allow-list (unknown fields/operators dropped) and compiled through the ordinary FilterCompiler (columns allow-listed, values bound) — it can only produce filters the grid already permits. No row data is sent to the model, only column metadata.
    • GridDefinition::ask(string $query, ?callable $engine = null): FilterGroup. The LLM call sits behind an injectable engine, so the validation/assembly is fully unit-tested without an API key (19 assertions).
    • Optional dependency on laravel/ai (a suggest); with no provider configured, ask() degrades gracefully.
    • Livewire client: opt-in public bool $assistant = true; renders an "ask" box in the toolbar that applies the translated filter to the builder.
    • Config: datagrid.assistant. Docs: guides/natural-language-filtering.md.
    • Verified end-to-end against Anthropic: correct AND/nested-OR trees.

Fixed

  • Protocol autoloading. The DTOs that share GridRequest.php / GridMutation.php (FilterCondition, FilterGroup, Viewport, Search, …) were only reachable once GridRequest/GridMutation had been referenced (PSR-4 maps class name to file name). Added a classmap autoload so every protocol class resolves on its own.

Tooling

  • New test:assistant suite and a schema-consistency check that the assistant's operator allow-list matches the protocol FilterOp enum. Both run in CI.

0.1.5 - 2026-07-21

Second hardening pass from the code review: Svelte parity, server guard rails, race protection on auxiliary fetches, and dependency/process fixes.

Fixed

  • Svelte client leaked on unmountDataGrid.svelte now calls GridController.destroy() via onDestroy (Vue already cleaned up via onScopeDispose).
  • Livewire row-id comparisons were loose (in_array($id, …, false)), so int-from-DB vs string-from-JS ids could mismatch. Selection/expanded/pinned membership now compares on the string form (isSelected/idIn/idIndex).
  • perPage <= 0 raised DivisionByZeroError — now clamped to ≥ 1 in updatedPerPage, pageCount, and the request builder.

Security

  • Request guard rails via GridLimits (config('datagrid.limits') or GridDefinition::limits()): max_take (1000), max_skip (100k, deep OFFSET was unbounded), max_filter_depth (15, filter recursion was unbounded), max_in_values (1000, IN lists were unbounded), max_export_rows (null = unlimited).
  • aggregatable is now enforced — aggregates on non-aggregatable columns are rejected (the flag was declared but never checked).
  • LIKE wildcards escaped%/_ in contains/startsWith/endsWith input are escaped with an ESCAPE clause, so "50%" matches literally.

Added

  • Column virtualization in the Svelte client (was missing entirely): renders only frozen columns plus the horizontal window, with spacer cells and onScrollX, matching the Vue client.
  • Race protection extended to auxiliary fetches (facets, tree roots, tree children, group detail): each discards its result if a superseding refresh changed the filter/search/sort mid-flight.

Dependencies / tooling

  • elyra/datagrid-server now requires illuminate/validation (the Validator facade was used but not declared).
  • elyra/datagrid-livewire now requires livewire/flux (the Blade uses flux:* components).
  • package-lock.json is now committed (was git-ignored) for reproducible CI.
  • New scripts/release.sh (npm run release <version>) automates the version bump, lockfile, bundle rebuild, test run, commit and tag.

0.1.4 - 2026-07-21

Hardening release following a full code review. Notably repairs the Svelte client, which was broken in 0.1.3.

Fixed

  • Svelte client was broken in 0.1.3. DataGrid.svelte referenced grid.features in the temporal dead zone (before its declaration), throwing ReferenceError on mount; the keyboard handler shadowed the GridController with a local boolean, throwing TypeError on Space/Enter/F2/Escape; and FilterBuilder.svelte imported FilterCondition/FilterOp, which @elyra/datagrid-client-core never re-exported. All fixed, and the shipped datagrid-js bundle rebuilt.

Security

  • Create validation bypass. On create, every editable column's rules are now applied, so required fires for omitted fields (previously only submitted fields were validated). Updates remain partial.
  • Hybrid-search vectorField allow-list. The client-supplied embedding column was quoted into SQL without an allow-list check; it is now resolved through the grid definition (rejected if undeclared) and passed as a driver-quoted reference.
  • XSS hardening. Row ids embedded into JS-evaluated attributes (Alpine dblclick, Livewire wire:click) are encoded with Illuminate\Support\Js, so string primary keys containing quotes or markup cannot break out.
  • Authorization gate. New GridDefinition::authorize() guards create/update/delete/export; denials throw GridException::unauthorized().

Added

  • debounceMs grid option (default 250): free-text search and column-filter values now debounce instead of firing a request per keystroke. Explicit actions (sort/paging/operator changes) are never debounced and cancel a pending typed refetch. (Response race protection already existed.)
  • isActiveRow(r) and FilterCondition/FilterOp re-exports on client-core.

Changed / Tooling

  • CI now typechecks the Vue and Svelte clients (vue-tsc + svelte-check), runs a PHP compiler/allow-list/authorization test suite (packages/server-laravel/tests/compilers.php), a protocol schema-consistency check (schema ↔ TS ↔ PHP), and a JS-bundle drift gate that fails if datagrid-js/dist is out of sync with the client sources.
  • Protocol docs now describe the contract honestly (hand-mirrored + checked in CI, not code-generated).

0.1.3 - 2026-07-21

Added

  • Double-click a row to edit. Double-clicking anywhere on a row now enters edit mode across all three clients (Livewire, Vue, Svelte). In in-cell mode it opens the cell you double-clicked when that cell is editable, otherwise the first editable cell of the row; in modal/slideover/inline modes it opens the row editor.
  • Tooltips on row command icons. The edit, pin/unpin, and delete icons now show hover tooltips. New localization keys pinRow, unpinRow, and deleteRow (English and Norwegian bundled).
  • isActiveRow(r) on the client-core grid controller.

Changed

  • Active-cell marker removed in favour of an active-row highlight. The boxed active-cell outline (and its heavy 2px focus ring) felt too dominant, especially with a dark accent colour in light mode. The active position is now conveyed by tinting the whole active row a quiet grey (.dg-row-active). The multi-cell range highlight used for copy is retained.
  • The aggregate footer can now stick to the bottom of a fixed-height scroll viewport (.dg-vscroll tfoot td). For virtual scroll, paged mode remains the reliable way to keep the footer always visible.

Fixed

  • In-cell editor never opened on double-click. editCell receives the row id as a string from the client ($wire.editCell('0', …)) while the row id is an integer, so the strict === comparison in the Livewire view never matched and the editor silently failed to render (no console error). Both sides are now compared as strings. Verified end-to-end with real dblclick events.
  • Row double-click now dispatches through a dedicated Alpine method (editRowCell$wire.editCell) instead of a fragile inline expression, and reads the double-clicked cell via data-editable.

0.1.2 - 2026-07-21

Fixed

  • Replaced inline @php(...) in shipped Blade with block @php … @endphp, which caused a fatal parse error on Laravel 13 + Livewire (including the license notice partial). Never use inline @php() in shipped Blade.

0.1.1 - 2026-07-21

Fixed

  • Additional Blade parsing fixes in the filter-builder partials on Laravel 13 + Livewire.

0.1.0 - 2026-07-21

Added

  • Initial release. One JSON protocol powering three clients (Livewire + Flux, Vue + Inertia, Svelte + Inertia) on a PHP server package with first-class ElyraSQL support and a MySQL fallback driver.
  • Columns, sorting (index-friendly stable tiebreaker), column filter row with operator picker, advanced AND/OR filter builder, global search.
  • Grouping with per-level aggregates (including non-additive avg/median/ percentile/countDistinct), detail rows, and roll-ups.
  • Paging with a numbered pager and page-size selector; opt-in totals, facets and aggregates cached per filter.
  • Editing in inline, modal, slideover and in-cell modes, plus batch/in-cell editing with dirty tracking.
  • Row selection, a full keyboard model, master-detail and self-referencing tree grids, left/right frozen columns with auto-fit, and virtual scroll.
  • Streaming XLSX/CSV export via bounded key-range windows.
  • Themeable via --dg-* variables that inherit the host app palette and Flux accent, with light/dark support.
  • Offline RSA-2048 license verification with graceful degradation and a discreet unlicensed notice. Commercial distribution via Private Packagist.