feat(plugins): add a Typesense driver with collection browsing and a request console (#2629) - #2648
Conversation
…request console (#2629) Claude-Session: https://claude.ai/code/session_01LikBUDFCMFdFRg1iZ9WWcw
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
…ver registers (#2629) Claude-Session: https://claude.ai/code/session_01LikBUDFCMFdFRg1iZ9WWcw
|
The docs screenshots are now real shots of the driver, captured against a local Typesense 29.0 at the canonical 3024x1722. Request console, light and dark A Driving the app to take these is what found the sixth defect: the plugin loaded but never registered its type, so the form offered to download a plugin that was already installed. The connection form itself is worth a look too, since it is the only place the |
…rver metrics (#2629) Claude-Session: https://claude.ai/code/session_01LikBUDFCMFdFRg1iZ9WWcw
# Conflicts: # docs/connections/ssh-tunneling.mdx # docs/connections/ssl.mdx


Adds a Typesense driver plugin: collections browse and edit as tables, and a request console that takes a method, a path and a JSON body the way the Typesense docs write their curl examples. Registry-only, like Elasticsearch.
Fixes #2629
What the server actually does
Every number and rule the driver hard-codes was measured against a real Typesense server (29.0 and 26.0, both downloaded and run locally), not read out of the docs. Five of them changed the design:
per_pageandlimitcap at 250 hits, and TablePro's default page is 1,000 rowsoffsetanswers correctly past a million, so no cursor or point-in-time is needed, unlike Elasticsearch.multi_searchcarries up to 50 searches; the 51st fails the whole batchmulti_search, so a 1,000-row page is a single round trip and a 100,000-row page is eight.sort_byon a field whose schema sayssort: falseis a 400 that fails the whole search,idis never sortable, and at most 3 sort fields are acceptedsortflag and capped at 3. A column that cannot sort stays unsorted instead of blanking the grid.filter_bybackticks have no escapetag:=`odd` || year:>0matched every document in the collection. A filter value containing a backtick is refused with a message.GET .../documents/searchURL over 4,096 bytes answers 400, which anINfilter reaches at 265 valuesPOST /multi_searchbody instead of a query string.Three more shaped smaller decisions: a string field under
>,<,>=or<=silently matches nothing rather than raising (so those are refused on a non-numeric field); a numeric or boolean field rejects a backticked literal (so quoting is driven by the declared type); and nested object fields are reported both as theobjectparent and as dotted leaves, alongside a.*entry on an auto-schema collection (so columns are the leaves, with the parents and the wildcard dropped andidprepended).scripts/check-typesense-limits.shre-checks all of that against a live server, so a future Typesense release cannot move one of these numbers silently.Filter mapping
=!=>>=<<=BETWEENINNOT INCONTAINSNOT CONTAINSSTARTS WITHall map ontofilter_by. Six do not exist in Typesense at all:IS NULL,IS NOT NULL,IS EMPTY,IS NOT EMPTY,REGEXandENDS WITH(which needs a field created withinfix: true). Those are refused with a localized message naming the operator rather than silently returning the wrong rows.String matching in Typesense always ignores case and nothing turns that off, so the plugin declares
caseSensitivityStyle = .unsupported..driverManagedwould have left the filter bar's case toggle enabled over a choice the driver cannot honour.Defects found in review and fixed here
Codex was out of usage limit, so a security reviewer and a correctness reviewer read the diff instead. Six findings, all in this branch's own code, all verified against the running server before fixing:
//attacker.example/xis an RFC 3986 network-path reference, soURL(string:relativeTo:)resolved it to a different host while theX-TYPESENSE-API-KEYheader rode along;GETalso classified.safe, so read-only mode and the MCP gate both passed it. Measured with a local listener: the admin key arrived. Every request now resolves throughTypesensePathEncoding.resolve, which refuses anything leaving the connection's scheme, host and port. Re-measured: blocked, listener saw nothing, ordinary console requests unaffected. The same shape exists in the Elasticsearch driver onmainand is listed below rather than changed here.POST /collections/c/documents/importcarrying"note": "/multi_search"in a field value classified as a read. It now parses the header line, cuts the path at?, and matches the path itself.year:=1900 || year:>0reached the server as filter syntax, on a branch chosen from a server-declared field type. Both now parse-check the value.a/bwas unreachable. Typesense accepts one;.urlPathAllowedlet the slash through, so the driver asked for/collections/a/band got a 404 while the collection listed in the sidebar. One shared path-segment encoder now encodes/and., which also stops a document id of..from ever acting as a path segment. Proven end to end: that collection now browses, counts and deletes.object[]column rendered blank. Typesense reportsvariants.skuas a schema field but returnsvariantsas an array of objects, and the flattener only walked dictionaries. A dotted path now reads across an array's elements, which is the same shape Typesense gives the leaf. Measured:["A1","B2"]where the grid previously showed nothing.TableProProvidesDatabaseTypeIds, soPluginManifestcould not read its type without loading it,isDriverInstalledanswered false, and picking Typesense in the form offered to download a plugin that was already installed. The app logs it: "declared no TableProProvides* capability keys in Info.plist; eager loading will block startup". Fixed and pinned by three tests that read the plist from the repository.Feature scope, and the four things that were broken
An audit against the full
PluginDatabaseDriversurface found that the driver was at Elasticsearch parity (24 of 251 requirements) and that four features the UI already offered did not work, because the app composes SQL whenever a driver declines to spell an operation itself:SELECT * FROM bookssupportsExportsaid yesDROP TABLE booksDELETE FROM booksDELETE /FROM booksstreamRowswas never implementedAll four now map to Typesense requests, measured against a live server: export streams
GET /collections/:c/documents/exportas JSONL and returned 1,200 rows in 3 batches with the right columns; truncate empties a collection and keeps its schema; drop removes the collection and leaves its neighbours; andDELETE FROM booksis now refused instead of becoming an HTTP request, while a query string holding a space still parses.Two Typesense-native surfaces were added on top:
/metrics.jsonand/stats.json: system and process memory, fragmentation, disk, requests per second, search and write latency, pending write batches and cache hit ratio.Compaction (
POST /operations/db/compact) is reachable in the console but deliberately not published throughsupportedMaintenanceOperations: both of the app's maintenance surfaces are scoped to the selected table, and compaction acts on the whole database, so listing it there would offer a per-collection item that silently acts on everything.Verification
verify.sh build,verify.sh generate: PASS.verify.sh testover the new suites plus every suite that owns a type this change touches: 90 + 95 + 77 cases, all passing, including a test per finding above.verify.sh plugins(AllPlugins):TypesenseDriverPlugin.tableplugincompiles, links and carries the right principal class and versions. The aggregate itself reports FAIL fromoracle-nio's@TaskLocalmacro under the local toolchain, a known local-only break unrelated to this change; the only two errors in the 8,744-line log are both in that package.verify.sh lint: 0 violations.docs/scripts/check-writing-style.shandcheck-docs-against-source.py: both clean, including the engine count moving 29 → 30 acrossdriver-counts.mdx,index.mdxanddatabases/index.mdx.scripts/ci/check-plugin-manifest.py: 30 plugins agree with the manifest.shellcheck --severity=warningclean over the new script.TypesensePluginDriverfrom aswiftcharness: connect, collection list with document counts, columns (nested leaves flattened, parents dropped), browse, browse sorted on a sortable and on an unsortable column, filtered browse and filtered count, a 600-row page arriving as 600 unique rows in order across three chunked searches, an offset page, the backtick filter refused,IS NULLrefused, the console overGET /collections,POST /multi_search, JSONL export and/health, and an insert / update / read-back / delete round trip.No UI automation: the flow needs a live Typesense server and a published registry binary, neither of which a deterministic UI test can assume.
Screenshot
docs/images/typesense-request-console.pngand its dark twin are real shots of the driver running against a local Typesense 29.0, captured at the canonical 3024x1722, not placeholders. Driving the app to get them is what surfaced finding 6.https://claude.ai/code/session_01LikBUDFCMFdFRg1iZ9WWcw