Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
359d79a
feat(modbus): the read-only client, register map and object tree for …
yusuf-gundogdu Oct 13, 2026
cb28fba
feat(modbus): the provider class, and the query dialect gap it carrie…
yusuf-gundogdu Oct 13, 2026
a5a3385
fix(modbus): refusals are QueryError, because the product treats a pl…
yusuf-gundogdu Oct 13, 2026
0dbf050
refactor(modbus): delete the stand-in declarations, which nothing rea…
yusuf-gundogdu Oct 13, 2026
0b07d92
test(modbus): int64 was declared and never tested, so the bigint rule…
yusuf-gundogdu Oct 13, 2026
55c1afc
feat(modbus): the socket dial, mirroring the shared egress helper's s…
yusuf-gundogdu Oct 13, 2026
11fea28
fix(modbus): the dial timer was unbound, and the tests for it were re…
yusuf-gundogdu Oct 13, 2026
f70bee2
fix(modbus): refusals leave through a boundary, and the type is chose…
yusuf-gundogdu Oct 13, 2026
b843717
test(modbus): four declared limits were not bound, and one test was c…
yusuf-gundogdu Oct 13, 2026
4f7a33a
fix(modbus): the inbound bound ran after the body was buffered, which…
yusuf-gundogdu Oct 13, 2026
1df6b20
test(modbus): bind the dropped bytes of a refused frame
yusuf-gundogdu Oct 13, 2026
5fe02cb
refactor(modbus): drop three published names nothing reads
yusuf-gundogdu Oct 13, 2026
dbd999d
revert(modbus): keep the 802 port constant, unread for now
yusuf-gundogdu Oct 13, 2026
3942d59
feat(modbus): parse the three read request shapes
yusuf-gundogdu Oct 13, 2026
9950b87
fix(modbus): an exchange checks the frame against the request it answers
yusuf-gundogdu Oct 13, 2026
c9ff649
refactor(modbus): the session carries the answer, not the bytes
yusuf-gundogdu Oct 13, 2026
725835b
feat(modbus): read one identification answer
yusuf-gundogdu Oct 13, 2026
2c0d0e4
test(modbus): hold three claims the suite was taking on trust
yusuf-gundogdu Oct 13, 2026
e704162
feat(modbus): register the provider across the surfaces that carry it
yusuf-gundogdu Oct 13, 2026
ab863b6
fix(modbus): close the surfaces the registration left silent
yusuf-gundogdu Oct 13, 2026
fccd865
test(modbus): bind two refusals by their reason, and the path guard a…
yusuf-gundogdu Oct 13, 2026
4c8f1b9
feat(modbus): reach the device, and measure it over a real socket
yusuf-gundogdu Oct 13, 2026
a3fbc34
fix(modbus): carry the destructive vocabulary row, and format what I …
yusuf-gundogdu Oct 13, 2026
18a9d1d
feat(modbus): dial when there is no map, so a wrong address cannot re…
yusuf-gundogdu Oct 13, 2026
32945b8
fix(modbus): follow the dial through to the tests it broke
yusuf-gundogdu Oct 13, 2026
340f745
fix(modbus): say what this provider lacks, not what the protocol lacks
yusuf-gundogdu Oct 13, 2026
3a4bf96
test(modbus): bind the socket's order and its closing, and fix a coun…
yusuf-gundogdu Oct 13, 2026
4b40825
feat(modbus): connect answers for the device, not only for the map
yusuf-gundogdu Oct 13, 2026
7474d19
test(modbus): hold the Test Connection answer at both ends, over the …
yusuf-gundogdu Oct 13, 2026
17bc6ac
feat(modbus): say that nothing was read when there is no map to read …
yusuf-gundogdu Oct 13, 2026
1c030ca
fix(modbus): convert the dial failure that carries no code of its own
yusuf-gundogdu Oct 13, 2026
0d9db88
docs(fleet): move every derived numeral, engine list and index row to…
yusuf-gundogdu Oct 14, 2026
5a34ab2
docs(backlog): re-measure D85's census, which grew by one after the e…
yusuf-gundogdu Oct 14, 2026
94ad7e8
fix(modbus): stop the masking rules starring out the register address
yusuf-gundogdu Oct 14, 2026
fe8b4c8
test(modbus): name the masking guard for the door it holds shut
yusuf-gundogdu Oct 14, 2026
7d7157a
test(modbus): a third-party fixture, and the integration layer the pr…
yusuf-gundogdu Oct 14, 2026
e7bd0f8
test(modbus): a live check against the third-party fixture, on Bun an…
yusuf-gundogdu Oct 14, 2026
3dadef7
test(modbus): hold the class a sibling engine was bitten by, where th…
yusuf-gundogdu Oct 14, 2026
e1f43e7
test(modbus): the browser spec, for the layer where the defect actual…
yusuf-gundogdu Oct 14, 2026
4c6d217
test(modbus): click twice, and hold the sentence that asks for the se…
yusuf-gundogdu Oct 14, 2026
ebaf443
test(modbus): run the query the way this suite runs one, and read the…
yusuf-gundogdu Oct 14, 2026
279c5fb
ci(modbus): the step, and a readiness check that a listening socket c…
yusuf-gundogdu Oct 15, 2026
599c7ff
ci(modbus): ask the server, not the port, and say which of the two fa…
yusuf-gundogdu Oct 15, 2026
64adb06
fix(modbus): make the digest a gate, name the version, and say which …
yusuf-gundogdu Oct 15, 2026
3b57cac
fix(modbus): give the registration the row the type checker named, an…
Oct 15, 2026
e36206c
test(modbus): give the browser spec the server and the project that r…
Oct 15, 2026
70787c7
docs(copy): count thirty-eight engines, and put the engine at the hea…
Oct 15, 2026
4945b1e
test(modbus): regenerate the dialect oracle, and name the engine the …
Oct 15, 2026
795231c
docs(fleet): re-derive the counts and name the engine where a registr…
Oct 15, 2026
9147a9c
docs(fleet): name the engine and re-derive the counts the registratio…
Oct 15, 2026
0c12b11
test(modbus): reach the arm of the refusal sentence no case had reached
Oct 15, 2026
4db6836
fix(modbus): read the identification body from its first byte
Oct 15, 2026
e108931
fix(modbus): import the socket class rather than requiring it
Oct 15, 2026
6c166a7
refactor(modbus): give the expectation reader's return type its name
Oct 15, 2026
0f098a3
refactor(modbus): drop the in-flight counter nothing reads
Oct 15, 2026
9aa18a8
test(modbus): drive the ends of a read the suite never reached
Oct 15, 2026
3bd7c89
docs(modbus): put the identification builder's line above that builder
Oct 15, 2026
6434f2e
docs(modbus): cite the symbol rather than a line number
Oct 15, 2026
cd01199
refactor(modbus): close the frame reader over its buffer
Oct 15, 2026
b9458e0
docs(rancher): leave one version-scoped instruction, not two that dis…
Oct 15, 2026
4e33c14
docs(rancher): take the room for Modbus from the claim that is made t…
Oct 15, 2026
68595a7
test(modbus): name the fake socket's buffer list in English
Oct 15, 2026
2399786
feat(modbus): give the register map a box, and the document a bound
Oct 15, 2026
38b548a
docs(api): name the register map in the documented connection shape
Oct 15, 2026
1e4ea13
test(modbus): hold the two choices the suite was not holding
Oct 15, 2026
189cab0
test(modbus): make the two maps the same length, and measure it
Oct 15, 2026
62b7bbb
fix(modbus): read the SSL/TLS panel, which asked for a field it does …
Oct 16, 2026
0af2694
test(modbus): read a device over mbaps, the way the reviewer could not
Oct 16, 2026
48d0cfa
refactor(modbus): write down the order the refusal sentences list val…
Oct 16, 2026
dd6f6b9
test(modbus): choose the device's table instead of indexing it by the…
Oct 16, 2026
6d8621a
test(modbus): compare unit ids as numbers where a block test sorts them
Oct 16, 2026
2cb27a6
test(modbus): skip the device cases where CI serves no device, and sa…
Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Guidance for Claude Code in this repo — conventions, rules, and gotchas only.

## Project Overview

Web-based SQL IDE for cloud-native teams: thirty-seven external engines, plus the embedded LibreDB store (`EXTERNAL_DATABASE_TYPES` in [`src/lib/db/compatibility.ts`](src/lib/db/compatibility.ts) is the external-engine list, never a prose enumeration), plus AI query assistance.
Web-based SQL IDE for cloud-native teams: thirty-eight external engines, plus the embedded LibreDB store (`EXTERNAL_DATABASE_TYPES` in [`src/lib/db/compatibility.ts`](src/lib/db/compatibility.ts) is the external-engine list, never a prose enumeration), plus AI query assistance.
It runs **two ways**, as a standalone Next.js app and as a published npm package, and the two render different chrome, so a UI change verified in one is not verified in the other.

## Branching & PRs
Expand Down
8 changes: 4 additions & 4 deletions DOCKERHUB.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ Every one of those tags is published on three bases, and the suffix is appended

## Supported databases

Thirty-seven external engines share one interface.
The thirty-eighth row is the embedded LibreDB store: it ships inside the image.
Thirty-eight external engines share one interface.
The thirty-ninth row is the embedded LibreDB store: it ships inside the image.

| Database | Driver | Highlights |
| :--- | :--- | :--- |
Expand Down Expand Up @@ -154,11 +154,11 @@ The thirty-eighth row is the embedded LibreDB store: it ships inside the image.
| **LibreDB** | `@libredb/libredb` | The embedded key-value store, for a database with nothing to install |

**Read-only where the engine is.** Druid, Elasticsearch and OpenSearch have no `UPDATE` and no `CREATE TABLE` anywhere in their grammar, so inline editing and DDL are reported as unsupported instead of failing when used.
Firestore, Prometheus, InfluxDB, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Oxia, S3-compatible object storage and Kubernetes are read-only too: Studio calls only read APIs.
Firestore, Prometheus, InfluxDB, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, Oxia, S3-compatible object storage and Kubernetes are read-only too: Studio calls only read APIs.

### Engines with no provider of their own

Twenty-seven further engines speak the wire protocol of one of the thirty-seven drivers above: pick that driver in the connection dialog. Each was measured against a real instance, and how much worked is recorded per engine.
Twenty-seven further engines speak the wire protocol of one of the thirty-eight drivers above: pick that driver in the connection dialog. Each was measured against a real instance, and how much worked is recorded per engine.

| Engine | Connect as | Support |
| :--- | :--- | :--- |
Expand Down
18 changes: 10 additions & 8 deletions README.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions README_es.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ Tomada en serio, esa frase deja de ser una preferencia y se vuelve una especific

## Capacidades principales

### Treinta y siete motores, una sola interfaz
### Treinta y ocho motores, una sola interfaz

PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect
PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus

Todos los motores SQL comparten el mismo explorador de esquemas, los diagramas ER, la comparación de esquemas y los paneles de monitoreo. MongoDB y Redis no son motores SQL: no tienen diagrama ER ni comparación de esquemas. Druid, Elasticsearch, OpenSearch y Trino son doblemente excepcionales: sus interfaces SQL sobre HTTP no tienen una forma de URI que este build sepa interpretar, así que se configuran por host y puerto, y las migraciones que se generan explican la limitación en lugar de inventar DDL para un motor cuyo SQL no tiene sentencias de cambio de columna. Lo mismo pasa con las colecciones sin esquema de Couchbase. El diagrama ER de los clústeres de búsqueda tiene cajas pero no líneas: los índices no declaran claves foráneas, y en el modelo del motor no hay ninguna que declarar.

Expand Down Expand Up @@ -157,6 +157,7 @@ Todos los motores SQL comparten el mismo explorador de esquemas, los diagramas E
| **RabbitMQ** | ninguno: la API HTTP de gestión (puerto 15672) y el cliente de lectura AMQP 0-9-1 propio de Studio (puerto 5672) | De solo lectura por construcción: el cliente de lectura no codifica publicaciones, extracciones ni declaraciones. Hosts virtuales, streams, colas y exchanges en el árbol; una petición de lectura JSON lee los mensajes de un stream, nunca los de una cola |
| **OPC UA** | `node-opcua-client` (JavaScript puro, `opc.tcp`, puerto 4840) | De solo lectura por construcción: la costura del cliente declara ocho servicios de lectura (GetEndpoints, CreateSession, ActivateSession, Browse, BrowseNext, Read, HistoryRead y CloseSession) y en el proveedor no hay Write, Call, HistoryUpdate ni suscripción alguna. El panel de claves recorre el espacio de direcciones nivel por nivel, un Browse por nivel, con la ruta de exploración escapada, porque un BrowseName puede contener el separador; un nodo se abre con su valor, su estado, sus dos marcas de tiempo y su AccessLevel descodificado, y la consola lee valores actuales o historial sin procesar como una sola petición JSON. Cada límite es el de Studio y no el que publica el servidor: de los cuatro servidores medidos, dos atienden peticiones muy por encima del límite que publican y uno lo publica como 0. Un nodo de método se lista y nunca se llama. Verificado con Microsoft OPC PLC 2.15.10, open62541 1.5.9, Python asyncua 2.1.0 y la demo de Eclipse Milo |
| **MTConnect** | ninguno: un cliente propio de este repositorio sobre el transporte `node:http(s)` compartido (puerto 5000) | De solo lectura por construcción: la tabla de rutas tiene nueve entradas y todas son GET, así que no hay PUT, POST ni stream que enviar. Un dispositivo es un contenedor, un data item y una condition son relaciones cuyas filas son valor, marca de tiempo y secuencia, y el XML de cada asset se abre en una pestaña Source |
| **Modbus** | ninguno: un cliente propio de este repositorio sobre un socket en crudo, a traves de la regla de salida compartida (puerto 502, u 802 para MODBUS/TCP Security) | Solo lectura por construccion: el codificador nombra cuatro codigos de funcion de lectura y la identificacion del dispositivo, ninguna funcion construye una escritura, y una valvula vuelve a comprobar cada byte que sale. Modbus no tiene descubrimiento, asi que el arbol se construye a partir de un mapa de registros guardado con la conexion, y una lectura es una sola peticion JSON sobre los puntos que ese mapa nombra |
| **Redis** | `ioredis` | Editor de comandos, explorador de claves, monitoreo basado en INFO |

> **La seguridad del transporte es transversal, no depende del motor.** El túnel SSH se abre antes de que el proveedor establezca la conexión y esta se redirige al extremo local, por lo que funciona independientemente del motor. Se aplica a cualquier conexión configurada con host y puerto, excepto Kafka, que no admite este túnel porque sus clientes se conectan a cada broker usando la dirección que este anuncia, y un túnel que redirige una sola dirección no puede cubrir todas esas conexiones. Las conexiones configuradas mediante una cadena de conexión (una opción disponible para MongoDB, Couchbase, ClickHouse y libSQL) no pasan por el túnel SSH porque no utilizan host y puerto por separado. SQLite y DuckDB tampoco tienen host ni puerto. El panel de SSL/TLS funciona en todos los motores que lo muestran. SQLite, DuckDB y LibreDB integrado no muestran este panel porque no tienen una conexión de red que proteger. En Trino, SSL/TLS es obligatorio porque el coordinador rechaza las contraseñas enviadas por HTTP sin cifrar. Oracle tiene una particularidad: su driver Thin siempre verifica la cadena de certificados, por lo que, si se usa `require` con un certificado autofirmado, es necesario proporcionar la CA del servidor. Además, si se pega una cadena de conexión completa, se conserva el protocolo que esta indique. Por su parte, Db2 LUW exige TLS de forma predeterminada, a menos que se desactive intencionalmente, porque sin esta protección el driver envía la contraseña sin cifrar.
Expand Down
5 changes: 3 additions & 2 deletions README_hi.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ LibreDB Studio दूसरा रास्ता चुनता है: **tool

## मुख्य क्षमताएँ

### सैंतीस engines, एक interface
### अड़तीस engines, एक interface

PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect
PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus

सभी SQL engines एक ही schema browser, ER diagram, schema diff और monitoring dashboard इस्तेमाल करते हैं। MongoDB और Redis SQL engines नहीं हैं, इसलिए उनमें ER diagram और schema diff नहीं है। Druid, Elasticsearch, OpenSearch और Trino दोहरे अपवाद हैं: उनके HTTP SQL interface का कोई ऐसा URI रूप नहीं है जिसे यह build पढ़ सके, इसलिए उन्हें सिर्फ़ host/port से configure किया जाता है। साथ ही, generated migration सीधे अपनी सीमा बताता है, बजाय ऐसे engine के लिए DDL बनाने के जिसकी SQL में column बदलने का कोई statement ही नहीं है। Couchbase के schemaless collections पर भी यही लागू है। Search clusters के ER diagram में सिर्फ़ boxes होते हैं, कोई line नहीं: indexes foreign keys declare नहीं करते, और engine के model में declare करने के लिए foreign key होती ही नहीं।

Expand Down Expand Up @@ -158,6 +158,7 @@ PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · Du
| **RabbitMQ** | कोई नहीं: प्रबंधन HTTP API (पोर्ट 15672) और Studio का अपना AMQP 0-9-1 पठन क्लाइंट (पोर्ट 5672) | संरचना से केवल-पठन: पठन क्लाइंट publish, संदेश निकालना या declare एन्कोड नहीं कर सकता। ट्री में वर्चुअल होस्ट, स्ट्रीम, क्यू और एक्सचेंज; JSON पठन अनुरोध स्ट्रीम के संदेश पढ़ता है, क्यू के कभी नहीं |
| **OPC UA** | `node-opcua-client` (शुद्ध JavaScript, `opc.tcp`, पोर्ट 4840) | बनावट से ही केवल-पढ़ने योग्य: क्लाइंट की सीम केवल आठ पढ़ने वाली सेवाएँ घोषित करती है (GetEndpoints, CreateSession, ActivateSession, Browse, BrowseNext, Read, HistoryRead और CloseSession), और प्रोवाइडर में Write, Call, HistoryUpdate या कोई सब्सक्रिप्शन कहीं नहीं है। कुंजी पैनल पता-स्थान को एक-एक स्तर पर, प्रति स्तर एक Browse से चलता है; कुंजी एस्केप किया हुआ ब्राउज़ पथ है, क्योंकि BrowseName में ही विभाजक आ सकता है। कोई नोड खुलने पर उसका मान, स्थिति, दोनों समय-चिह्न और समझा गया AccessLevel दिखता है, और कंसोल एक ही JSON अनुरोध से वर्तमान मान या कच्चा इतिहास पढ़ता है। हर सीमा Studio की अपनी है, सर्वर की घोषित सीमा नहीं: मापे गए चार सर्वरों में से दो अपनी घोषित सीमा से कहीं आगे के अनुरोध भी पूरे करते हैं और एक उसे 0 घोषित करता है। मेथड नोड सूची में आता है, कभी नहीं चलाया जाता। Microsoft OPC PLC 2.15.10, open62541 1.5.9, Python asyncua 2.1.0 और Eclipse Milo डेमो पर सत्यापित |
| **MTConnect** | कोई नहीं: साझा `node:http(s)` transport पर इस repository का अपना client (पोर्ट 5000) | बनावट से ही read-only: request table में नौ routes हैं और हर एक GET है, इसलिए भेजने के लिए कोई PUT, POST या stream नहीं। device एक container है, data item और condition ऐसी relations हैं जिनकी पंक्तियाँ value, timestamp और sequence हैं, और हर asset का XML Source टैब में खुलता है |
| **Modbus** | कोई नहीं: साझा egress नियम से गुजरते हुए raw socket पर इस repository का अपना client (पोर्ट 502, MODBUS/TCP Security के लिए 802) | बनावट से read-only: encoder केवल चार read function code और device identification बनाता है, कोई function लिखना नहीं बना सकता, और एक valve बाहर जाने वाले हर byte को दोबारा जाँचता है। Modbus में discovery नहीं है, इसलिए tree connection के साथ रखे register map से बनता है, और एक read उस map के नाम दिए points पर एक JSON request है |
| **Redis** | `ioredis` | Command editor, key browser, INFO पर आधारित monitoring |

> **Transport security हर engine की अलग सुविधा नहीं, सब पर लागू होने वाली क्षमता है।** SSH tunnel provider के connect होने से पहले ही बन जाता है और connection को local endpoint पर मोड़ देता है, इसलिए यह engine पर निर्भर नहीं: जिस connection में host और port हो, उस पर यह लागू होता है, Kafka connection को छोड़कर: Kafka client हर broker तक उसके advertised address पर पहुँचता है, जिसे एक address forward करने वाला tunnel नहीं ले जा सकता, इसलिए Kafka connection tunnel मना कर देता है। Connection string से भरे गए connections (MongoDB, Couchbase और ClickHouse में यह तरीका है) में host/port नहीं होता, इसलिए वे tunnel से नहीं जाते। SQLite और DuckDB में भी दोनों नहीं होते। SSL/TLS panel अभी PostgreSQL, MySQL, SQL Server, Couchbase, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Prometheus और Apache Kafka पर काम करता है। Trino पर यह वैकल्पिक नहीं है, क्योंकि coordinator plain HTTP पर password मना कर देता है। Oracle, MongoDB और Redis इस setting को नज़रअंदाज़ करते हैं, इसलिए इन तीनों में encryption इस पर निर्भर है कि connection string में क्या लिखा है, dialog में क्या चुना है इस पर नहीं।
Expand Down
Loading
Loading