- Extract reusable helpers for database and table action permission preloading.
- Precompute those permissions before building table-page HTML data.
- Document the default table actions plugin.
- Use a per-process socket path for the UDS test fixture.
- Clean up stale socket files before and after the fixture runs.
- Close the HTTP client and wait for the Datasette subprocess to exit.
- Register a built-in table action and expose alter-table metadata to table pages.
- Build the client-side modal for editing columns, defaults, ordering, primary keys, and custom column types.
- Add a review/apply confirmation flow with HTML and Playwright coverage.
Refs #2788
- Add POST /<database>/<table>/-/alter with Pydantic validation and dry-run support.
- Support add, rename, alter, drop, primary-key and reorder operations, including allow-listed default expressions.
- Document the endpoint and cover schema changes, validation, permissions, events and dry runs.
Refs #2788
Adds a permission-gated database action that opens a create table modal on database pages, backed by the existing create-table JSON API.
The modal starts with an id integer primary key column plus a blank text column, supports SQLite type selection, and shows custom column type controls only when the actor can set column types.
Selected custom column types are applied after table creation with follow-up set-column-type API calls. Includes styling plus HTML and Playwright coverage for the action payload and create-table flow.
Previously there were four lines of whitespace, but that
meant users had to delete that whitespace themselves when
they started editing. Now it is four lines tall without that.
Add a Create table starter template to the execute-write page, alongside the existing table-specific insert/update/delete templates.
Keep template button clicks in-page by updating CodeMirror and the URL without collapsing the template controls.
Refresh schema metadata after successful schema-changing execute-write statements so newly created tables appear immediately.
PR #2781
- A new `/db/table/-/autocomplete?q=term` JSON API for fast autocomplete search against foreign key tables - it searches against their label column or their primary key and switches to just a prefix search against the first primary key (for speed) if the label column check takes more than 500ms. A new `/-/debug/autocomplete` page lets you try this out.
- A `<datasette-autocomplete>` Web Component that uses that API.
- Table pages now get an insert button above the table, and little edit and delete icons next to each row. All three trigger custom modal dialogs. The edit/insert dialog is a full form - the delete one is just confirmation.
- A new `/<database>/<table>/-/fragment?_row=` endpoint which returns a rendered fragment of HTML for the specified row. This is used by the insert/edit code to partially update the table to reflect those changes. Uses a new `data-row="{{ row.row_path }}"` attribute on the `<tr>` to enable the replacement.
- A new default column type called `textarea` which users can use to specify a multi-line textarea for a column
- A new JavaScript plugin hook, [makeColumnField()](3f7d389caf/docs/javascript_plugins.rst (makecolumnfieldcontext)), which plugins can use to add custom form fields to the edit form. Datasette [uses this itself](3f7d389caf/datasette/static/table.js (L1181-L1209)) for the JSON field to add client-side JSON validation. I iterated a *lot* on this one, including spinning up a `datasette-prosemirror` plugin and a branch of `datasette-files` to fully exercise it.
Closes#2780
Video demo: https://github.com/user-attachments/assets/2c18b8a4-975f-4c7b-9573-ec6040fe8223
- Simplify JavaScript column field context:
- expose `isPk` instead of `isPrimaryKey`
- expose `defaultExpression` instead of separate SQLite default flags
- remove value/default state from plugin context
- Update field helper behavior:
- `setValue()` no longer dispatches input/change events
- remove dispatch options and `resetValue()`
- add `markClean()` for plugin-normalized initial values
- track clean field state for reliable dirty detection
Also:
- Prompt before closing row insert/edit dialogs when there are unsaved changes
- Map declared SQLite types to affinities, returning `BLOB` for typeless columns and `NUMERIC` for numeric/date/boolean-like declarations
Replace the value/valueType/originalValue/originalValueType fields on makeColumnField() contexts with an explicit field object API for reading, writing, resetting, comparing and validating field values.
Normalize columnType to {type, config}, rename the SQLite default metadata so it is clearly SQLite-specific, and document that plugins submit only string, number, boolean or null values. Plugins that need structured data should serialize it themselves instead of relying on Datasette to special-case JSON.
Move the built-in json column type behavior onto the same plugin API used by external plugins: validate the textarea with field.setValidity() as the value changes, but submit plain text. Harden row edit value comparison so fixing invalid JSON in an existing row is not blocked by the original invalid value.
Update the JavaScript plugin documentation and Node-based tests for the revised field contract.
Expose single-primary-key foreign key autocomplete URLs in table page metadata and load the autocomplete component when needed.
Enhance insert and edit dialogs to wrap foreign-key inputs with the autocomplete web component, show linked selected-row labels, reserve metadata space, and keep the dropdown as a fixed overlay above modal chrome.
Add an explicit _initial=1 autocomplete mode for empty-field starter suggestions while keeping blank q responses empty by default, with tests for the endpoint and table metadata.