@rip-lang/db 0.8.5 → 0.10.0

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/db.html CHANGED
@@ -9,7 +9,8 @@
9
9
  h1 { margin: 0 0 20px; font-size: 24px; color: #fff; }
10
10
  .container { max-width: 1200px; margin: 0 auto; }
11
11
  textarea { width: 100%; height: 120px; padding: 12px; font-family: 'Monaco', 'Menlo', monospace; font-size: 14px; background: #16213e; color: #0f0; border: 1px solid #0f4c75; border-radius: 6px; resize: vertical; }
12
- button { padding: 10px 24px; font-size: 14px; background: #0f4c75; color: #fff; border: none; border-radius: 6px; cursor: pointer; margin: 10px 10px 10px 0; }
12
+ .buttons { margin: 10px 0; }
13
+ button { padding: 10px 24px; font-size: 14px; background: #0f4c75; color: #fff; border: none; border-radius: 6px; cursor: pointer; margin-right: 10px; }
13
14
  button:hover { background: #1b6ca8; }
14
15
  .info { font-size: 12px; color: #888; margin-bottom: 10px; }
15
16
  .results { margin-top: 20px; }
@@ -29,48 +30,93 @@
29
30
  <h1>đŸĻ† DuckDB Console</h1>
30
31
  <div class="info">Connected to: <span id="db">loading...</span></div>
31
32
  <textarea id="sql" placeholder="SELECT * FROM users LIMIT 10;">SELECT * FROM users;</textarea>
32
- <div>
33
- <button onclick="runQuery()">â–ļ Run (Cmd+Enter)</button>
34
- <button onclick="showTables()">📋 Tables</button>
35
- <button onclick="showStatus()">â„šī¸ Status</button>
33
+ <div class="buttons">
34
+ <button onclick="run()">â–ļ Run (Cmd+Enter)</button>
35
+ <button onclick="tables()">📋 Tables</button>
36
+ <button onclick="status()">â„šī¸ Status</button>
36
37
  </div>
37
38
  <div id="results" class="results"></div>
38
39
  </div>
39
40
  <script>
40
- fetch('/status').then(r => r.json()).then(d => document.getElementById('db').textContent = d.database);
41
- document.getElementById('sql').addEventListener('keydown', e => {
42
- if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') runQuery();
41
+ const sqlEl = document.getElementById('sql');
42
+ const resultsEl = document.getElementById('results');
43
+
44
+ // Load status on startup
45
+ fetch('/status').then(r => r.json()).then(d => {
46
+ document.getElementById('db').textContent = d.database;
43
47
  });
44
- async function runQuery() {
45
- const sql = document.getElementById('sql').value.trim();
48
+
49
+ // Cmd+Enter to run
50
+ sqlEl.addEventListener('keydown', e => {
51
+ if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
52
+ e.preventDefault();
53
+ run();
54
+ }
55
+ });
56
+
57
+ function run() {
58
+ const sql = sqlEl.value.trim();
46
59
  if (!sql) return;
47
- try {
48
- const res = await fetch('/sql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sql }) });
49
- renderResult(await res.json());
50
- } catch (e) { renderError(e.message); }
60
+ fetch('/sql', {
61
+ method: 'POST',
62
+ headers: { 'Content-Type': 'application/json' },
63
+ body: JSON.stringify({ sql })
64
+ })
65
+ .then(r => r.json())
66
+ .then(renderResult)
67
+ .catch(e => renderError(e.message));
51
68
  }
52
- async function showTables() {
53
- document.getElementById('sql').value = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'main';";
54
- runQuery();
69
+
70
+ function tables() {
71
+ sqlEl.value = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'main';";
72
+ run();
55
73
  }
56
- async function showStatus() {
57
- try {
58
- const data = await (await fetch('/status')).json();
59
- document.getElementById('results').innerHTML = '<div style="background:#16213e;padding:16px;border-radius:6px;"><div><strong>Database:</strong> ' + data.database + '</div><div><strong>Tables:</strong> ' + (data.tables?.join(', ') || 'none') + '</div><div><strong>Time:</strong> ' + data.time + '</div></div>';
60
- } catch (e) { renderError(e.message); }
74
+
75
+ function status() {
76
+ fetch('/status')
77
+ .then(r => r.json())
78
+ .then(data => {
79
+ resultsEl.innerHTML = `
80
+ <div style="background:#16213e;padding:16px;border-radius:6px;">
81
+ <div><strong>Database:</strong> ${data.database}</div>
82
+ <div><strong>Tables:</strong> ${data.tables?.join(', ') || 'none'}</div>
83
+ <div><strong>Time:</strong> ${data.time}</div>
84
+ </div>`;
85
+ })
86
+ .catch(e => renderError(e.message));
61
87
  }
88
+
62
89
  function renderResult(data) {
63
- if (data.error) { renderError(data.error); return; }
64
- if (!data.meta?.length) { document.getElementById('results').innerHTML = '<div class="meta"><span class="status ok">✓ OK</span> Query executed in ' + data.time + 's</div>'; return; }
90
+ if (data.error) {
91
+ renderError(data.error);
92
+ return;
93
+ }
94
+ if (!data.meta?.length) {
95
+ resultsEl.innerHTML = `<div class="meta"><span class="status ok">✓ OK</span> Query executed in ${data.time}s</div>`;
96
+ return;
97
+ }
65
98
  let html = '<table><tr>';
66
- data.meta.forEach(col => { html += '<th>' + col.name + '<br><span style="font-weight:normal;font-size:11px;color:#888">' + col.type + '</span></th>'; });
99
+ data.meta.forEach(col => {
100
+ html += `<th>${col.name}<br><span style="font-weight:normal;font-size:11px;color:#888">${col.type}</span></th>`;
101
+ });
67
102
  html += '</tr>';
68
- data.data.forEach(row => { html += '<tr>'; row.forEach(val => { html += '<td>' + (val === null ? '<span style="color:#666">NULL</span>' : val) + '</td>'; }); html += '</tr>'; });
69
- html += '</table><div class="meta"><span class="status ok">✓ OK</span> ' + data.rows + ' row' + (data.rows !== 1 ? 's' : '') + ' in ' + data.time + 's</div>';
70
- document.getElementById('results').innerHTML = html;
103
+ data.data.forEach(row => {
104
+ html += '<tr>';
105
+ row.forEach(val => {
106
+ html += `<td>${val === null ? '<span style="color:#666">NULL</span>' : val}</td>`;
107
+ });
108
+ html += '</tr>';
109
+ });
110
+ html += `</table><div class="meta"><span class="status ok">✓ OK</span> ${data.rows} row${data.rows !== 1 ? 's' : ''} in ${data.time}s</div>`;
111
+ resultsEl.innerHTML = html;
112
+ }
113
+
114
+ function renderError(msg) {
115
+ resultsEl.innerHTML = `<div class="error"><span class="status err">✗ Error</span> ${msg}</div>`;
71
116
  }
72
- function renderError(msg) { document.getElementById('results').innerHTML = '<div class="error"><span class="status err">✗ Error</span> ' + msg + '</div>'; }
73
- runQuery();
117
+
118
+ // Run initial query
119
+ run();
74
120
  </script>
75
121
  </body>
76
122
  </html>
package/db.rip CHANGED
@@ -3,20 +3,24 @@
3
3
  # ==============================================================================
4
4
  #
5
5
  # A simple HTTP server for DuckDB queries. One server per database.
6
- # Compatible with the official DuckDB UI (duckdb -ui) via binary protocol.
6
+ # Fully compatible with the official DuckDB UI!
7
7
  #
8
8
  # Usage:
9
9
  # rip db.rip <database.duckdb> [--port 4000]
10
10
  # rip db.rip :memory: --port 4000
11
11
  #
12
+ # Then open http://localhost:4000/ for the official DuckDB UI!
13
+ # (UI assets are proxied from ui.duckdb.org)
14
+ #
12
15
  # Endpoints:
13
- # POST /sql - Execute SQL (query or mutation)
16
+ # GET / - Official DuckDB UI (proxied from ui.duckdb.org)
17
+ # GET /ui - Built-in SQL console (simple, no proxy)
18
+ # POST /sql - Execute SQL (JSON API)
14
19
  # POST /ddb/run - DuckDB UI binary protocol
15
- # GET /health - Health check (always ok)
16
- # GET /status - Database info and table list
17
- # GET /tables - List all tables
18
- # GET /schema/:table - Get table schema
19
- # GET /ui - Built-in SQL console
20
+ # GET /health - Health check
21
+ # GET /status - Database info
22
+ # GET /tables - List tables
23
+ # GET /schema/:table - Table schema
20
24
  #
21
25
  # ==============================================================================
22
26
 
@@ -36,6 +40,14 @@ import {
36
40
  # Enable CORS for duck-ui and other clients
37
41
  use cors preflight: true
38
42
 
43
+ # Log all requests
44
+ use (c, next) ->
45
+ start = Date.now()
46
+ result = next!
47
+ ms = Date.now() - start
48
+ console.log "#{c.req.method} #{c.req.path} #{ms}ms"
49
+ result
50
+
39
51
  # ==============================================================================
40
52
  # Configuration
41
53
  # ==============================================================================
@@ -54,7 +66,7 @@ if '--help' in args or '-h' in args
54
66
  database Path to DuckDB file (default: :memory:)
55
67
 
56
68
  Options:
57
- --port=N Port to listen on (default: 4000)
69
+ --port=N Port to listen on (default: 4213)
58
70
  --help Show this help
59
71
  --version Show version
60
72
 
@@ -70,7 +82,7 @@ if '--help' in args or '-h' in args
70
82
  GET /schema/:t Get schema for table t
71
83
 
72
84
  Examples:
73
- rip db.rip # In-memory database on port 4000
85
+ rip db.rip # In-memory database on port 4213
74
86
  rip db.rip mydb.duckdb # File-based database
75
87
  rip db.rip :memory: --port=8080
76
88
 
@@ -85,7 +97,7 @@ if '--version' in args or '-v' in args
85
97
 
86
98
  # Support both env vars (for rip-server) and CLI args (for rip db.rip)
87
99
  path = process.env.DB_PATH or args.find((a) -> not a.startsWith('-')) or ':memory:'
88
- port = parseInt(process.env.DB_PORT or (args.find((a) -> a.startsWith('--port=')))?.split('=')[1]) or 4000
100
+ port = parseInt(process.env.DB_PORT or (args.find((a) -> a.startsWith('--port=')))?.split('=')[1]) or 4213
89
101
 
90
102
  # Open database
91
103
  db = open(path)
@@ -97,7 +109,8 @@ console.log "rip-db: database=#{path} (bun-native)"
97
109
 
98
110
  # Extract column info from result
99
111
  getColumnInfo = (rows) ->
100
- return { columns: [], types: [] } unless rows?.length > 0
112
+ if not rows?.length > 0
113
+ return { columns: [], types: [] }
101
114
  first = rows[0]
102
115
  columns = Object.keys(first)
103
116
  types = columns.map (col) ->
@@ -155,18 +168,18 @@ executeSQL = (sql, params = []) ->
155
168
  # ==============================================================================
156
169
 
157
170
  # POST / — duck-ui compatible (raw SQL in body)
158
- post '/', ->
159
- sql = read().body
160
- console.log "POST /", sql
161
- return { error: 'Empty query' } unless sql?.trim()
171
+ post '/' ->
172
+ sql = read 'body', 'string'
173
+ if not sql
174
+ return { error: 'Empty query' }
162
175
  executeSQL sql
163
176
 
164
177
  # POST /sql — JSON body with optional params
165
- post '/sql', ->
178
+ post '/sql' ->
166
179
  { sql, params } = read()
167
- console.log "POST /sql", sql, params or []
168
- return { error: 'Missing required field: sql' } unless sql
169
- executeSQL sql, params or []
180
+ if not sql
181
+ return { error: 'Missing required field: sql' }
182
+ executeSQL sql, (params or [])
170
183
 
171
184
  # GET /health — Simple health check (no DB query)
172
185
  get '/health', ->
@@ -239,15 +252,14 @@ get '/ui', -> new Response Bun.file(import.meta.dir + '/db.html')
239
252
  # ==============================================================================
240
253
 
241
254
  # POST /ddb/run — Execute SQL and return binary result (DuckDB UI protocol)
242
- post '/ddb/run', (req) ->
255
+ post '/ddb/run' ->
243
256
  try
244
- sql = req.text!
245
- console.log "POST /ddb/run", sql?.slice?(0, 100) or sql
257
+ sql = read 'body', 'string'
258
+ if not sql
259
+ return binaryResponse serializeErrorResult 'Empty query'
246
260
 
247
- return binaryResponse serializeErrorResult 'Empty query' unless sql?.trim()
248
-
249
- # Parse result row limit from headers
250
- rowLimit = parseInt(req.headers.get('x-duckdb-ui-result-row-limit') or '10000')
261
+ # Parse row limit from DuckDB UI header
262
+ rowLimit = parseInt(@req.header('x-duckdb-ui-result-row-limit') or '10000')
251
263
 
252
264
  # Execute query
253
265
  conn = db.connect()
@@ -270,9 +282,9 @@ post '/ddb/run', (req) ->
270
282
  finally
271
283
  conn.close()
272
284
 
273
- catch error
274
- console.error "POST /ddb/run error:", error.message
275
- binaryResponse serializeErrorResult error.message or String(error)
285
+ catch err
286
+ console.error "POST /ddb/run error:", err?.message
287
+ binaryResponse serializeErrorResult err?.message or 'Unknown error'
276
288
 
277
289
  # POST /ddb/interrupt — Cancel running query
278
290
  post '/ddb/interrupt', ->
@@ -281,24 +293,110 @@ post '/ddb/interrupt', ->
281
293
  binaryResponse serializeEmptyResult()
282
294
 
283
295
  # POST /ddb/tokenize — Tokenize SQL for syntax highlighting
284
- post '/ddb/tokenize', (req) ->
285
- sql = req.text! or ''
296
+ post '/ddb/tokenize' ->
297
+ sql = read 'body', 'string'
286
298
  tokens = tokenizeSQL sql
287
299
  binaryResponse serializeTokenizeResult tokens
288
300
 
301
+ # GET /version — Tell UI we're running in local/HTTP mode (not WASM)
302
+ get '/version' ->
303
+ { origin: 'local', version: '139-944c08a214' }
304
+
305
+ # GET /localToken — Return empty token for local mode (no MotherDuck)
306
+ get '/localToken' ->
307
+ new Response '', { status: 200, headers: { 'Content-Type': 'text/plain' } }
308
+
289
309
  # GET /info — Server version info (DuckDB UI checks this)
290
- get '/info', (req, res) ->
291
- res.headers.set 'Access-Control-Allow-Origin', '*'
292
- res.headers.set 'X-DuckDB-Version', '1.2.1' # Pretend to be DuckDB
293
- res.headers.set 'X-DuckDB-Platform', 'rip-db'
294
- res.headers.set 'X-DuckDB-UI-Extension-Version', VERSION
295
- ''
310
+ # The UI checks X-DuckDB-UI-Extension-Version to decide HTTP vs WASM mode
311
+ # Version format must match desiredDuckDBUIExtensionVersions in /config
312
+ get '/info' ->
313
+ @body '', 200,
314
+ 'Access-Control-Allow-Origin': '*'
315
+ 'X-DuckDB-Version': '1.4.1'
316
+ 'X-DuckDB-Platform': 'rip-db'
317
+ 'X-DuckDB-UI-Extension-Version': '139-944c08a214'
296
318
 
297
319
  # Helper to create binary response
298
320
  binaryResponse = (buffer) ->
299
321
  new Response buffer,
300
322
  headers: { 'Content-Type': 'application/octet-stream' }
301
323
 
324
+ # ==============================================================================
325
+ # DuckDB UI Proxy — Serve official UI assets from ui.duckdb.org
326
+ # ==============================================================================
327
+ #
328
+ # The official DuckDB UI is a React app hosted at https://ui.duckdb.org
329
+ # We proxy these assets so you can use the beautiful UI with rip-db!
330
+ #
331
+ # The UI makes API requests to relative URLs (/ddb/run, /ddb/tokenize, etc.)
332
+ # which we handle above. This proxy just serves the static UI assets.
333
+ #
334
+ # ==============================================================================
335
+
336
+ UI_REMOTE_URL = 'https://ui.duckdb.org'
337
+
338
+ # GET /localEvents — Server-sent events for catalog updates
339
+ get '/localEvents' ->
340
+ # Create SSE response with keep-alive
341
+ encoder = new TextEncoder()
342
+ intervalId = null
343
+
344
+ stream = new ReadableStream
345
+ start: (controller) ->
346
+ # Send initial connection event
347
+ controller.enqueue encoder.encode "event: connected\ndata: {}\n\n"
348
+
349
+ # Keep connection alive with periodic heartbeats
350
+ intervalId = setInterval ->
351
+ try
352
+ controller.enqueue encoder.encode ": heartbeat\n\n"
353
+ catch
354
+ clearInterval intervalId
355
+ , 30000
356
+
357
+ cancel: ->
358
+ clearInterval intervalId if intervalId
359
+
360
+ new Response stream,
361
+ headers:
362
+ 'Content-Type': 'text/event-stream'
363
+ 'Cache-Control': 'no-cache'
364
+ 'Connection': 'keep-alive'
365
+
366
+ # GET /* — Proxy UI assets from ui.duckdb.org (catch-all, must be last)
367
+ get '/*' ->
368
+ path = @req.path
369
+
370
+ # Skip if this is one of our API endpoints (shouldn't reach here, but safety)
371
+ return { error: 'Not found' } if path in ['/health', '/status', '/tables', '/info', '/ui']
372
+
373
+ try
374
+ # Fetch from remote UI server
375
+ response = fetch! "#{UI_REMOTE_URL}#{path}",
376
+ headers:
377
+ 'User-Agent': "rip-db/#{VERSION}"
378
+
379
+ # Get response body and content type
380
+ body = response.arrayBuffer!
381
+ contentType = response.headers.get('Content-Type') or 'application/octet-stream'
382
+
383
+ # Build response headers
384
+ headers =
385
+ 'Content-Type': contentType
386
+ 'Cache-Control': response.headers.get('Cache-Control') or 'public, max-age=3600'
387
+
388
+ # For /config endpoint, add DuckDB version headers (UI uses these to detect mode)
389
+ if path is '/config'
390
+ headers['X-DuckDB-Version'] = '1.4.1'
391
+ headers['X-DuckDB-Platform'] = 'rip-db'
392
+ headers['X-DuckDB-UI-Extension-Version'] = '139-944c08a214'
393
+
394
+ new Response body, { status: response.status, headers }
395
+
396
+ catch err
397
+ console.error "Proxy error for #{path}:", err?.message
398
+ new Response "Failed to fetch UI asset: #{path}", { status: 502 }
399
+
302
400
  # ==============================================================================
303
401
  # Start Server
304
402
  # ==============================================================================
@@ -306,4 +404,5 @@ binaryResponse = (buffer) ->
306
404
  start port: port
307
405
 
308
406
  console.log "rip-db: listening on http://localhost:#{port}"
309
- console.log "rip-db: POST /sql, POST /ddb/run, GET /health, GET /status, GET /tables, GET /schema/:table, GET /ui"
407
+ console.log "rip-db: Official DuckDB UI available at http://localhost:#{port}/"
408
+ console.log "rip-db: Built-in console at http://localhost:#{port}/ui"
@@ -229,28 +229,25 @@ serializeVector = (s, column, values) ->
229
229
  s.writeFieldId 101
230
230
  s.writeData createValidityBitmap values
231
231
 
232
- # Type IDs: VARCHAR=25, CHAR=24, BOOLEAN=10, TINYINT=11, UTINYINT=28,
233
- # SMALLINT=12, USMALLINT=29, INTEGER=13, UINTEGER=30, BIGINT=14, UBIGINT=31,
234
- # FLOAT=22, DOUBLE=23, DATE=15, TIMESTAMP=19, TIMESTAMP_TZ=32
235
232
  switch typeId
236
- when 25, 24 # VARCHAR, CHAR
233
+ when LogicalTypeId.VARCHAR, LogicalTypeId.CHAR
237
234
  s.writeList 102, values, (s, v) -> s.writeString String(v ? '')
238
235
 
239
- when 10 # BOOLEAN
236
+ when LogicalTypeId.BOOLEAN
240
237
  s.writeFieldId 102
241
238
  bytes = new Uint8Array values.length
242
239
  for v, i in values
243
240
  bytes[i] = if v then 1 else 0
244
241
  s.writeData bytes
245
242
 
246
- when 11, 28 # TINYINT, UTINYINT
243
+ when LogicalTypeId.TINYINT, LogicalTypeId.UTINYINT
247
244
  s.writeFieldId 102
248
245
  bytes = new Uint8Array values.length
249
246
  for v, i in values
250
247
  bytes[i] = (v ? 0) & 0xFF
251
248
  s.writeData bytes
252
249
 
253
- when 12 # SMALLINT
250
+ when LogicalTypeId.SMALLINT
254
251
  s.writeFieldId 102
255
252
  bytes = new Uint8Array values.length * 2
256
253
  dv = new DataView bytes.buffer
@@ -258,7 +255,7 @@ serializeVector = (s, column, values) ->
258
255
  dv.setInt16 i * 2, v ? 0, true
259
256
  s.writeData bytes
260
257
 
261
- when 29 # USMALLINT
258
+ when LogicalTypeId.USMALLINT
262
259
  s.writeFieldId 102
263
260
  bytes = new Uint8Array values.length * 2
264
261
  dv = new DataView bytes.buffer
@@ -266,7 +263,7 @@ serializeVector = (s, column, values) ->
266
263
  dv.setUint16 i * 2, v ? 0, true
267
264
  s.writeData bytes
268
265
 
269
- when 13 # INTEGER
266
+ when LogicalTypeId.INTEGER
270
267
  s.writeFieldId 102
271
268
  bytes = new Uint8Array values.length * 4
272
269
  dv = new DataView bytes.buffer
@@ -274,7 +271,7 @@ serializeVector = (s, column, values) ->
274
271
  dv.setInt32 i * 4, v ? 0, true
275
272
  s.writeData bytes
276
273
 
277
- when 30 # UINTEGER
274
+ when LogicalTypeId.UINTEGER
278
275
  s.writeFieldId 102
279
276
  bytes = new Uint8Array values.length * 4
280
277
  dv = new DataView bytes.buffer
@@ -282,7 +279,7 @@ serializeVector = (s, column, values) ->
282
279
  dv.setUint32 i * 4, v ? 0, true
283
280
  s.writeData bytes
284
281
 
285
- when 14 # BIGINT
282
+ when LogicalTypeId.BIGINT
286
283
  s.writeFieldId 102
287
284
  bytes = new Uint8Array values.length * 8
288
285
  dv = new DataView bytes.buffer
@@ -290,7 +287,7 @@ serializeVector = (s, column, values) ->
290
287
  dv.setBigInt64 i * 8, BigInt(v ? 0), true
291
288
  s.writeData bytes
292
289
 
293
- when 31 # UBIGINT
290
+ when LogicalTypeId.UBIGINT
294
291
  s.writeFieldId 102
295
292
  bytes = new Uint8Array values.length * 8
296
293
  dv = new DataView bytes.buffer
@@ -298,7 +295,7 @@ serializeVector = (s, column, values) ->
298
295
  dv.setBigUint64 i * 8, BigInt(v ? 0), true
299
296
  s.writeData bytes
300
297
 
301
- when 22 # FLOAT
298
+ when LogicalTypeId.FLOAT
302
299
  s.writeFieldId 102
303
300
  bytes = new Uint8Array values.length * 4
304
301
  dv = new DataView bytes.buffer
@@ -306,7 +303,7 @@ serializeVector = (s, column, values) ->
306
303
  dv.setFloat32 i * 4, v ? 0, true
307
304
  s.writeData bytes
308
305
 
309
- when 23 # DOUBLE
306
+ when LogicalTypeId.DOUBLE
310
307
  s.writeFieldId 102
311
308
  bytes = new Uint8Array values.length * 8
312
309
  dv = new DataView bytes.buffer
@@ -314,7 +311,7 @@ serializeVector = (s, column, values) ->
314
311
  dv.setFloat64 i * 8, v ? 0, true
315
312
  s.writeData bytes
316
313
 
317
- when 15 # DATE
314
+ when LogicalTypeId.DATE
318
315
  s.writeFieldId 102
319
316
  bytes = new Uint8Array values.length * 4
320
317
  dv = new DataView bytes.buffer
@@ -323,7 +320,7 @@ serializeVector = (s, column, values) ->
323
320
  dv.setInt32 i * 4, days, true
324
321
  s.writeData bytes
325
322
 
326
- when 19, 32 # TIMESTAMP, TIMESTAMP_TZ
323
+ when LogicalTypeId.TIMESTAMP, LogicalTypeId.TIMESTAMP_TZ
327
324
  s.writeFieldId 102
328
325
  bytes = new Uint8Array values.length * 8
329
326
  dv = new DataView bytes.buffer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/db",
3
- "version": "0.8.5",
3
+ "version": "0.10.0",
4
4
  "description": "DuckDB Server — Simple HTTP API for DuckDB queries",
5
5
  "type": "module",
6
6
  "main": "db.rip",
@@ -12,9 +12,6 @@
12
12
  "dev": "rip db.rip :memory:",
13
13
  "test": "bun test"
14
14
  },
15
- "dependencies": {
16
- "@rip-lang/api": "^0.5.0"
17
- },
18
15
  "keywords": [
19
16
  "db",
20
17
  "database",