@rip-lang/db 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -120
- package/bin/rip-db +4 -9
- package/db.rip +224 -230
- package/lib/duckdb-binary.rip +546 -0
- package/lib/duckdb.mjs +727 -250
- package/package.json +8 -11
- package/INTERNALS.md +0 -324
- package/build.zig +0 -88
- package/lib/darwin-arm64/duckdb.node +0 -0
- package/src/duckdb.zig +0 -1156
package/README.md
CHANGED
|
@@ -2,176 +2,159 @@
|
|
|
2
2
|
|
|
3
3
|
# Rip DB - @rip-lang/db
|
|
4
4
|
|
|
5
|
-
> **DuckDB server with the official DuckDB UI**
|
|
5
|
+
> **A lightweight DuckDB HTTP server with the official DuckDB UI built in**
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Rip DB turns any DuckDB database into a full-featured HTTP server — complete
|
|
8
|
+
with the official DuckDB UI for interactive queries, notebooks, and data
|
|
9
|
+
exploration. It connects to DuckDB via pure Bun FFI (no npm packages, no
|
|
10
|
+
native build step) and implements DuckDB's binary serialization protocol
|
|
11
|
+
to power the UI with native-speed data transfer.
|
|
9
12
|
|
|
10
13
|
## Quick Start
|
|
11
14
|
|
|
12
15
|
```bash
|
|
13
|
-
# Install
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# Install DuckDB and Rip DB
|
|
17
|
+
brew install duckdb # macOS (or see duckdb.org for Linux)
|
|
18
|
+
bun add -g @rip-lang/db # Installs rip-db command
|
|
19
|
+
|
|
20
|
+
# Start the server
|
|
21
|
+
rip-db # In-memory database
|
|
22
|
+
rip-db mydata.duckdb # File-based database
|
|
23
|
+
rip-db mydata.duckdb --port 8080
|
|
24
|
+
```
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
rip-db mydata.duckdb
|
|
26
|
+
Open **http://localhost:4213** for the official DuckDB UI.
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
rip-db --port=8080
|
|
24
|
-
```
|
|
28
|
+
## What It Does
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
Rip DB sits between your clients and DuckDB, providing two interfaces:
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
```
|
|
33
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
34
|
+
│ DuckDB UI │ binary │ rip-db │ FFI │ DuckDB │
|
|
35
|
+
│ (Browser) │◀────────▶│ (Bun) │◀────────▶│ (native) │
|
|
36
|
+
└─────────────┘ └─────────────┘ └─────────────┘
|
|
37
|
+
▲
|
|
38
|
+
│ HTTP/S
|
|
39
|
+
│ (JSON)
|
|
40
|
+
▼
|
|
41
|
+
┌─────────────────┐
|
|
42
|
+
│ HTTP Clients │
|
|
43
|
+
│ (curl, apps) │
|
|
44
|
+
└─────────────────┘
|
|
45
|
+
```
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
**DuckDB UI** — The official DuckDB notebook interface loads instantly in your
|
|
48
|
+
browser. Rip DB proxies the UI assets from ui.duckdb.org and implements the
|
|
49
|
+
full binary serialization protocol that the UI uses to communicate with DuckDB.
|
|
50
|
+
This includes query execution, SQL tokenization for syntax highlighting, and
|
|
51
|
+
Server-Sent Events for real-time catalog updates.
|
|
34
52
|
|
|
35
|
-
|
|
53
|
+
**JSON API** — Any HTTP client can execute SQL queries and receive JSON
|
|
54
|
+
responses. Use it from curl, your application code, or any language that
|
|
55
|
+
speaks HTTP.
|
|
36
56
|
|
|
37
|
-
|
|
57
|
+
## Features
|
|
38
58
|
|
|
39
|
-
|
|
59
|
+
- **Official DuckDB UI** — Interactive notebooks, syntax highlighting, data exploration
|
|
60
|
+
- **Full binary protocol** — Native DuckDB UI serialization implemented in Rip
|
|
61
|
+
- **Pure Bun FFI** — Direct calls to DuckDB's C API using the modern chunk-based interface
|
|
62
|
+
- **Zero npm dependencies for DuckDB** — Uses the system-installed DuckDB library
|
|
63
|
+
- **Parameterized queries** — Prepared statements with type-safe parameter binding
|
|
64
|
+
- **Complete type support** — All DuckDB types handled natively, including UUID, DECIMAL, TIMESTAMP, LIST, STRUCT, MAP
|
|
65
|
+
- **DECIMAL precision preserved** — Exact string representation, never converted to floating point
|
|
66
|
+
- **Timestamps as UTC** — All timestamps returned as JavaScript Date objects (UTC)
|
|
67
|
+
- **Powered by @rip-lang/api** — Fast, lightweight HTTP server framework
|
|
68
|
+
- **Single binary** — One `rip-db` command, one process, one database
|
|
40
69
|
|
|
41
|
-
|
|
42
|
-
|----------|--------|---------|
|
|
43
|
-
| `/` | GET | Official DuckDB UI |
|
|
44
|
-
| `/ddb/run` | POST | Execute SQL (binary) |
|
|
45
|
-
| `/ddb/tokenize` | POST | Syntax highlighting |
|
|
46
|
-
| `/ddb/interrupt` | POST | Cancel query |
|
|
70
|
+
## JSON API
|
|
47
71
|
|
|
48
|
-
|
|
72
|
+
For programmatic access from any HTTP client.
|
|
49
73
|
|
|
50
|
-
|
|
74
|
+
### POST /sql
|
|
51
75
|
|
|
52
|
-
|
|
76
|
+
Execute SQL with optional parameters:
|
|
53
77
|
|
|
54
78
|
```bash
|
|
55
79
|
curl -X POST http://localhost:4213/sql \
|
|
56
80
|
-H "Content-Type: application/json" \
|
|
57
|
-
-d '{"sql": "SELECT * FROM users WHERE id = 1"}'
|
|
81
|
+
-d '{"sql": "SELECT * FROM users WHERE id = $1", "params": [1]}'
|
|
58
82
|
```
|
|
59
83
|
|
|
60
|
-
|
|
61
|
-
```json
|
|
62
|
-
{
|
|
63
|
-
"meta": [{"name": "id", "type": "INTEGER"}, {"name": "name", "type": "VARCHAR"}],
|
|
64
|
-
"data": [[1, "Alice"]],
|
|
65
|
-
"rows": 1,
|
|
66
|
-
"time": 0.001
|
|
67
|
-
}
|
|
68
|
-
```
|
|
84
|
+
### POST /
|
|
69
85
|
|
|
70
|
-
|
|
86
|
+
Execute raw SQL (body is the query):
|
|
71
87
|
|
|
72
88
|
```bash
|
|
73
89
|
curl -X POST http://localhost:4213/ -d "SELECT 42 as answer"
|
|
74
90
|
```
|
|
75
91
|
|
|
76
|
-
|
|
92
|
+
Response format:
|
|
77
93
|
|
|
78
94
|
```json
|
|
79
|
-
{
|
|
95
|
+
{
|
|
96
|
+
"meta": [{"name": "answer", "type": "INTEGER"}],
|
|
97
|
+
"data": [[42]],
|
|
98
|
+
"rows": 1,
|
|
99
|
+
"time": 0.001
|
|
100
|
+
}
|
|
80
101
|
```
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
### Other Endpoints
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
| Endpoint | Method | Description |
|
|
106
|
+
|----------|--------|-------------|
|
|
107
|
+
| `/health` | GET | Health check |
|
|
108
|
+
| `/tables` | GET | List all tables |
|
|
109
|
+
| `/schema/:table` | GET | Table schema |
|
|
87
110
|
|
|
88
|
-
|
|
111
|
+
## DuckDB UI
|
|
89
112
|
|
|
90
|
-
|
|
91
|
-
{"ok": true, "tables": ["users", "orders"]}
|
|
92
|
-
```
|
|
113
|
+
The official DuckDB UI is available at the root URL. It provides:
|
|
93
114
|
|
|
94
|
-
**
|
|
115
|
+
- **SQL Notebooks** — Write and execute queries in a notebook interface
|
|
116
|
+
- **Syntax Highlighting** — Real-time SQL tokenization as you type
|
|
117
|
+
- **Data Exploration** — Browse tables, schemas, and query results
|
|
118
|
+
- **Multiple Databases** — Attach and query across databases
|
|
95
119
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
## Building from Source
|
|
120
|
+
The UI communicates with Rip DB using DuckDB's binary serialization protocol,
|
|
121
|
+
which Rip DB implements in full. This means the UI works exactly as it does
|
|
122
|
+
with the official `duckdb -ui` command — same features, same performance.
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
## How It Works
|
|
103
125
|
|
|
104
|
-
|
|
105
|
-
cd packages/db
|
|
126
|
+
Rip DB is built from three files:
|
|
106
127
|
|
|
107
|
-
|
|
108
|
-
|
|
128
|
+
| File | Lines | Role |
|
|
129
|
+
|------|-------|------|
|
|
130
|
+
| `db.rip` | ~390 | HTTP server — routes, middleware, UI proxy |
|
|
131
|
+
| `lib/duckdb.mjs` | ~800 | FFI driver — modern chunk-based DuckDB C API |
|
|
132
|
+
| `lib/duckdb-binary.rip` | ~550 | Binary serializer — DuckDB UI protocol |
|
|
109
133
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
The FFI driver uses DuckDB's modern chunk-based API (`duckdb_fetch_chunk`,
|
|
135
|
+
`duckdb_vector_get_data`) to read query results directly from columnar memory.
|
|
136
|
+
No deprecated per-value functions, no intermediate copies. For complex types
|
|
137
|
+
like DECIMAL, ENUM, LIST, and STRUCT, it uses DuckDB's logical type
|
|
138
|
+
introspection to read values with full fidelity.
|
|
113
139
|
|
|
114
|
-
|
|
140
|
+
The binary serializer implements the same wire protocol that DuckDB's official
|
|
141
|
+
UI extension uses. It handles all DuckDB types including native 16-byte UUID
|
|
142
|
+
serialization, uint64-aligned validity bitmaps, and proper timestamp encoding.
|
|
115
143
|
|
|
116
|
-
|
|
117
|
-
DUCKDB_DIR=/path/to/duckdb zig build
|
|
118
|
-
```
|
|
144
|
+
## Requirements
|
|
119
145
|
|
|
120
|
-
|
|
146
|
+
- **Bun** 1.0+
|
|
147
|
+
- **DuckDB** library installed on the system
|
|
148
|
+
- macOS: `brew install duckdb`
|
|
149
|
+
- Linux: Install from [duckdb.org](https://duckdb.org/docs/installation)
|
|
150
|
+
- **rip-lang** 2.8+ (installed automatically as a dependency)
|
|
121
151
|
|
|
122
|
-
|
|
152
|
+
Set `DUCKDB_LIB_PATH` if DuckDB is not in a standard location:
|
|
123
153
|
|
|
124
154
|
```bash
|
|
125
|
-
|
|
126
|
-
zig build -Dtarget=aarch64-linux-gnu # Linux ARM64
|
|
127
|
-
zig build -Dtarget=x86_64-windows # Windows x64
|
|
128
|
-
zig build -Dtarget=aarch64-macos # macOS ARM64
|
|
129
|
-
zig build -Dtarget=x86_64-macos # macOS x64
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
**Note:** Cross-compiling requires DuckDB libraries for each target platform.
|
|
133
|
-
For production, use CI/CD with native builds on each OS (GitHub Actions runners).
|
|
134
|
-
|
|
135
|
-
## Architecture
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
139
|
-
│ DuckDB UI │ binary │ rip-db │ FFI │ DuckDB │
|
|
140
|
-
│ (Browser) │◀────────▶│ (Bun) │◀────────▶│ (native) │
|
|
141
|
-
└─────────────┘ └─────────────┘ └─────────────┘
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
- **Single FFI call** per query (not per-value)
|
|
145
|
-
- **Zero-copy** for numeric columns
|
|
146
|
-
- **Binary serialization in Zig** — no JavaScript overhead
|
|
147
|
-
- **Pre-allocated buffers** — no allocations per query
|
|
148
|
-
|
|
149
|
-
See [INTERNALS.md](./INTERNALS.md) for protocol details.
|
|
150
|
-
|
|
151
|
-
## Files
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
packages/db/
|
|
155
|
-
├── build.zig # Zig build configuration
|
|
156
|
-
├── src/
|
|
157
|
-
│ └── duckdb.zig # Native Zig bindings
|
|
158
|
-
├── lib/
|
|
159
|
-
│ ├── duckdb.mjs # Bun FFI wrapper
|
|
160
|
-
│ └── darwin-arm64/
|
|
161
|
-
│ └── duckdb.node # Compiled library
|
|
162
|
-
├── bin/
|
|
163
|
-
│ └── rip-db # CLI entry point
|
|
164
|
-
├── db.rip # Server implementation
|
|
165
|
-
├── README.md # This file
|
|
166
|
-
└── INTERNALS.md # Protocol & architecture details
|
|
155
|
+
DUCKDB_LIB_PATH=/path/to/libduckdb.dylib rip-db
|
|
167
156
|
```
|
|
168
157
|
|
|
169
|
-
## Requirements
|
|
170
|
-
|
|
171
|
-
- Bun 1.0+
|
|
172
|
-
- rip-lang 2.0+
|
|
173
|
-
- @rip-lang/api 0.5+
|
|
174
|
-
|
|
175
158
|
## License
|
|
176
159
|
|
|
177
160
|
MIT
|
package/bin/rip-db
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
4
|
import { dirname, join } from 'path';
|
|
6
5
|
|
|
7
|
-
const
|
|
8
|
-
const __dirname = dirname(__filename);
|
|
9
|
-
|
|
10
|
-
const dbRip = join(__dirname, '..', 'db.rip');
|
|
11
|
-
const args = process.argv.slice(2);
|
|
6
|
+
const dbRip = join(dirname(new URL(import.meta.url).pathname), '..', 'db.rip');
|
|
12
7
|
|
|
13
8
|
try {
|
|
14
|
-
execFileSync('rip', [dbRip, ...
|
|
15
|
-
} catch (
|
|
16
|
-
process.exit(
|
|
9
|
+
execFileSync('rip', [dbRip, ...process.argv.slice(2)], { stdio: 'inherit' });
|
|
10
|
+
} catch (e) {
|
|
11
|
+
process.exit(e.status || 1);
|
|
17
12
|
}
|