Single source of truth for the CodeMirror setup: SQLiteDialect,
createSqlEditor() (delegable history with host undo/redo forwarding,
hostChange annotation for echo suppression, submit/escape callbacks,
fixed-tooltip mode, per-editor Compartment updateSchema), and
datasetteSchema() which fetches /-/editor-schema.json and maps it to a
lang-sql SQLNamespace identical to the server-inlined shape.
cm-editor.js is now a thin consumer; rollup emits both the IIFE and an
importable ESM bundle. Submit key is Mod-Enter (Cmd on mac as before,
now also Ctrl elsewhere) plus Shift-Enter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follow-up to d12f0d2c: the test regexes the inlined schema= JS and
still asserted the old flat list-of-strings shape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The table page's 'View and edit SQL' link now carries ?_table=<name>;
QueryView validates it against the actor-visible tables/views for the
database before exposing it as default_table, so the editor completes
that table's columns unprefixed. Stored/canned queries are unaffected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Neutral {database, tables: [{name, view, columns: [{name, type}]}]}
shape, gated on view-database + execute-sql with no table-name leak on
403, hidden tables excluded. /-/schema.json was already taken by the
DDL endpoint, hence editor-schema.json. _editor_schema() now maps from
the shared _schema_tables() introspection helper.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per-view Compartment wraps the sql() extension; window.editor.updateSchema(
{schema, defaultTable, defaultSchema}) reconfigures autocomplete live.
Declares @codemirror/state as a direct dependency since it is now
imported directly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_editor_schema() emits lang-sql Completion objects (column type as
detail, boost above keywords) and gives views their real columns via
PRAGMA table_xinfo in a self/children container labelled 'view'.
_table_columns() is unchanged for the write-template path. Note the
table_columns field in the database JSON context now carries this
richer shape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cm-editor-6.0.1.{js,bundle.js} -> cm-editor.{js,bundle.js}; new
npm run build:codemirror replaces the documented rollup one-liner.
Cache busting already handled by the static() template helper's
?_hash= content hash.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
codemirror 6.0.1 -> 6.0.2, @codemirror/lang-sql 6.3.3 -> 6.10.0
(autocomplete 6.20.3, view 6.43.6, state 6.7.1).
defaultTableName/defaultSchemaName were never valid SQLConfig options;
the real names are defaultTable/defaultSchema. Also enables
caseInsensitiveIdentifiers on the SQLite dialect.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
named_parameters stripped SQL comments before string literals in
separate passes. A string literal such as '-- TODO' would be treated
as the start of a line comment, swallowing the rest of the line and
hiding any named parameters that followed it. For example:
select * from t where note = '-- TODO' and id = :id
returned [] instead of ['id'], so the query parameter input form
would be missing the :id field.
Match comments and string literals in a single left-to-right pass so
that whichever construct starts first wins, matching how SQL is
actually tokenized.
Co-authored-by: JSap0914 <JSap0914@users.noreply.github.com>
The alias existed so API payloads could mirror the params key used by
queries defined in datasette.yaml, but it was undocumented and untested,
and the create endpoint is not part of the stable API. The API now only
accepts parameters - sending params is a 400 Invalid keys error. The
documented params key for queries in configuration is unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
Documents the canonical error format, the ok/envelope changes, the
array-to-object endpoint conversions, 401s for invalid tokens, the
pagination and page-size unification, removed legacy keys and formats,
and the new Response.error(), TokenInvalid, count_truncated and
unstable-marker APIs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
next_url became a default table JSON key alongside next, making the
extra a no-op. Requesting ?_extra=next_url now returns the standard
unknown-extra 400 error.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
Response.error(messages, status=400) builds a JSON error response in
Datasette's standard error format, alongside Response.json/html/text.
messages can be a single string or a list. All internal error response
construction now uses it - the private views.base._error() helper is
gone and the verbose Response.json(error_body(...), status=...) sites
are converted. error_body() remains for the cases that merge the error
keys into a larger payload (the JSON renderer, handle_exception and the
permission debug payload builders).
Since Response is public plugin API, plugins that build JSON endpoints
now have an obvious way to return errors in the canonical shape.
Documented in the internals documentation, including the guidance to
raise Forbidden/NotFound/BadRequest/DatasetteError instead when the
error should content-negotiate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
existing-api.md and stable-api-recommendations.md were working
documents for the 1.0 API consistency review. Their content remains
available in this branch history; they are not intended to merge to
main.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
The SQL time limit error embedded an HTML fragment (paragraph, textarea
and script tags) as the error string in JSON responses. DatasetteError
now accepts a plain_message which the exception handler prefers for
JSON error bodies; the HTML error page keeps the rich message with the
SQL textarea.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
The insert, upsert, alter and set-column-type endpoints previously
required Content-Type: application/json while /-/create parsed the body
blind - and insert returned a 500 AttributeError when the header was
missing entirely. The lenient rule is now uniform: the body is always
parsed as JSON and invalid JSON is a 400. This makes curl -d and
requests data=json.dumps(...) invocations work without remembering the
header. Cross-site request forgery remains prevented by the Origin and
Sec-Fetch-Site checks in CrossOriginProtectionMiddleware, which is the
defense the strict content-type requirement was historically standing
in for.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
/-/config redacts values for keys whose names contain secret, key,
password, token, hash or dsn. Plugins that follow that naming get
automatic redaction; plugins that don't will leak their secrets on
that endpoint.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
Boolean arguments parsed by value_as_boolean() accept on/true/1 and
off/false/0 - state this once in the JSON API docs rather than leaving
each argument to imply its own grammar.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
An upsert may update existing rows without creating anything, so it
deliberately does not claim resource creation with a 201.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
next: null (with next_url: null) is the single end-of-results signal
across the API, keeping default response keys to a minimum. The
StoredQueryPage.has_more attribute on the documented Python API is
unchanged.
Also fixes a bug this uncovered: the query list JSON next_url pointed
at the HTML page (it was built from the query list path, dropping the
.json extension) and was a relative path where the table view next_url
is absolute. It is now built from the request path and absolute, so it
preserves the requested format and can be followed directly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
Two tests merged from main were written against the pre-merge response
shapes: the max_post_body_bytes 413 error now uses the canonical error
envelope, and row update with return:true responds with a rows list
rather than a singular row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ