Skip to content

Commit 0d57d67

Browse files
committed
feat: Refactor database client to support multiple drivers (Postgres, Libsql, Neon)
- Introduced a unified client class `DriftSQLClient` to handle queries across different database drivers. - Added support for PostgreSQL using both `pg` and `postgres` libraries. - Implemented Libsql client integration with a result conversion method. - Added placeholder for Neon client integration. - Updated query methods to return a unified result type. - Enhanced CRUD operations to work with generic table structures. - Added error handling and logging for database operations. - Implemented a `close` method to properly terminate database connections.
1 parent 200e2ee commit 0d57d67

File tree

6 files changed

+913
-88
lines changed

6 files changed

+913
-88
lines changed

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
test.ts
1+
test.ts
2+
.env

README.md

Lines changed: 130 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,163 @@
1-
# @lassejlv/postgres-http-driver
1+
# DriftSQL
22

33
<!-- automd:badges color=yellow -->
44

5-
[![npm version](https://img.shields.io/npm/v/@lassejlv/postgres-http-driver?color=yellow)](https://npmjs.com/package/@lassejlv/postgres-http-driver)
6-
[![npm downloads](https://img.shields.io/npm/dm/@lassejlv/postgres-http-driver?color=yellow)](https://npm.chart.dev/@lassejlv/postgres-http-driver)
5+
[![npm version](https://img.shields.io/npm/v/driftsql?color=yellow)](https://npmjs.com/package/driftsql)
6+
[![npm downloads](https://img.shields.io/npm/dm/driftsql?color=yellow)](https://npm.chart.dev/driftsql)
77

88
<!-- /automd -->
99

10-
Driver for Postgres HTTP Server (docker.com/lassejlv/postgres_http). This package provides a TypeScript client for connecting to PostgreSQL databases over HTTP, offering a simple and type-safe interface for database operations.
10+
A lightweight SQL client for TypeScript, supporting multiple databases like PostgreSQL, LibSQL, and HTTP-based database services. DriftSQL provides a unified, type-safe interface for database operations across different database drivers.
1111

1212
## Features
1313

1414
- 🔐 Type-safe database operations with TypeScript generics
1515
- 🛡️ SQL injection protection with parameterized queries
16-
- 🚀 Simple HTTP-based connection (no native PostgreSQL driver required)
16+
- 🚀 Multiple driver support (PostgreSQL, LibSQL, HTTP)
1717
- 📝 Auto-completion support for database schema types
1818
- ⚡ Built-in error handling and connection management
19+
- 🔄 Unified API across different database types
20+
21+
## Supported Drivers
22+
23+
- **PostgreSQL** - Native PostgreSQL driver via `pg`
24+
- **LibSQL** - SQLite-compatible databases via `@libsql/client`
25+
- **HTTP** - HTTP-based database services
26+
- **Neon** - Neon serverless PostgreSQL (experimental)
1927

2028
## Usage
2129

2230
Install the package:
2331

2432
```sh
2533
# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
26-
npx nypm install @lassejlv/postgres-http-driver
34+
npx nypm install driftsql
2735
```
2836

2937
Import and use:
3038

31-
<!-- automd:jsimport cdn name="@lassejlv/postgres-http-driver" -->
39+
<!-- automd:jsimport cdn name="driftsql" -->
3240

3341
**ESM** (Node.js, Bun, Deno)
3442

3543
```js
36-
import { PostgresHTTPClient } from "@lassejlv/postgres-http-driver";
44+
import { DriftSQLClient } from 'driftsql'
3745
```
3846

3947
**CDN** (Deno, Bun and Browsers)
4048

4149
```js
42-
import { PostgresHTTPClient } from "https://esm.sh/@lassejlv/postgres-http-driver";
50+
import { DriftSQLClient } from 'https://esm.sh/driftsql'
4351
```
4452

4553
<!-- /automd -->
4654

4755
## Quick Start
4856

49-
```typescript
50-
import { PostgresHTTPClient } from '@lassejlv/postgres-http-driver'
57+
### Define Your Database Schema
5158

52-
// Initialize the client
53-
const db = new PostgresHTTPClient({
54-
url: 'https://your-postgres-http-server.com',
55-
password: 'your-bearer-token',
56-
options: {
57-
defaultTimeout: 5000 // optional, defaults to 5000ms
58-
}
59-
})
59+
```typescript
60+
import { DriftSQLClient } from 'driftsql'
6061

61-
// Define your table interface for type safety
62+
// Define your database schema types
6263
interface User {
6364
id: number
6465
name: string
6566
email: string
6667
created_at: string
6768
}
6869

70+
interface Post {
71+
id: number
72+
title: string
73+
content: string | null
74+
user_id: number | null
75+
published: boolean
76+
created_at: Date
77+
updated_at: Date
78+
}
79+
80+
// Define your database schema
81+
interface MyDatabase {
82+
users: User
83+
posts: Post
84+
}
85+
```
86+
87+
### Initialize with PostgreSQL
88+
89+
```typescript
90+
const db = new DriftSQLClient<MyDatabase>({
91+
drivers: {
92+
postgres: {
93+
connectionString: 'postgresql://user:password@localhost:5432/mydb',
94+
// or individual options:
95+
// host: 'localhost',
96+
// port: 5432,
97+
// database: 'mydb',
98+
// user: 'user',
99+
// password: 'password'
100+
},
101+
},
102+
})
103+
```
104+
105+
### Initialize with LibSQL
106+
107+
```typescript
108+
const db = new DriftSQLClient<MyDatabase>({
109+
drivers: {
110+
libsql: {
111+
url: 'file:local.db',
112+
// or for remote:
113+
// url: 'libsql://your-database.turso.io',
114+
// authToken: 'your-auth-token'
115+
},
116+
},
117+
})
118+
```
119+
120+
### Initialize with HTTP
121+
122+
```typescript
123+
const db = new DriftSQLClient<MyDatabase>({
124+
url: 'https://your-database-api.com',
125+
password: 'your-bearer-token',
126+
options: {
127+
defaultTimeout: 5000, // optional, defaults to 5000ms
128+
},
129+
})
130+
```
131+
132+
### Database Operations
133+
134+
```typescript
69135
// Raw SQL queries
70-
const users = await db.query<User>('SELECT * FROM users WHERE active = $1', ['true'])
136+
const users = await db.query<User>('SELECT * FROM users WHERE active = $1', [true])
71137
console.log(users.rows)
72138

73139
// Find operations
74-
const user = await db.findFirst<User>({ email: '[email protected]' }, 'users')
75-
const activeUsers = await db.findMany<User>({ active: true }, 'users')
140+
const user = await db.findFirst('users', { email: '[email protected]' })
141+
const activeUsers = await db.findMany('users', { active: true })
76142

77143
// Insert operations
78-
const newUser = await db.insert<User>('users', {
144+
const newUser = await db.insert('users', {
79145
name: 'John Doe',
80-
146+
81147
})
82148

83149
// Update operations
84-
const updatedUser = await db.update<User>('users',
85-
{ name: 'Jane Doe' },
86-
{ id: 1 }
87-
)
150+
const updatedUser = await db.update('users', { name: 'Jane Doe' }, { id: 1 })
88151

89152
// Delete operations
90-
const deleted = await db.delete<User>('users', { id: 1 })
153+
const deleted = await db.delete('users', { id: 1 })
91154

92-
// Check server status
155+
// Check server status (HTTP only)
93156
const status = await db.status()
94157
console.log(`Database OK: ${status.ok}, Ping: ${status.ping}ms`)
158+
159+
// Clean up connections
160+
await db.close()
95161
```
96162

97163
## API Reference
@@ -100,23 +166,46 @@ console.log(`Database OK: ${status.ok}, Ping: ${status.ping}ms`)
100166

101167
```typescript
102168
interface ClientOptions {
103-
url: string // HTTP server URL
104-
password: string // Bearer token for authentication
169+
url?: string // HTTP server URL (for HTTP driver)
170+
password?: string // Bearer token for HTTP authentication
171+
drivers?: {
172+
libsql?: LibsqlClientConfig // LibSQL configuration
173+
postgres?: PoolConfig // PostgreSQL configuration
174+
postgresNeonHTTP?: {
175+
// Neon configuration (experimental)
176+
connectionString: string
177+
}
178+
}
105179
options?: {
106-
defaultTimeout?: number // Request timeout in milliseconds
180+
defaultTimeout?: number // Request timeout in milliseconds
107181
}
108182
}
109183
```
110184

111185
### Methods
112186

113-
- `query<T>(sql: string, args?: string[])` - Execute raw SQL with parameters
114-
- `findFirst<T>(where: Partial<T>, table: string)` - Find first matching record
115-
- `findMany<T>(where: Partial<T>, table: string)` - Find all matching records
116-
- `insert<T>(table: string, data: Partial<T>)` - Insert new record
117-
- `update<T>(table: string, data: Partial<T>, where: Partial<T>)` - Update records
118-
- `delete<T>(table: string, where: Partial<T>)` - Delete records
119-
- `status()` - Get server status and ping
187+
- `query<T>(sql: string, args?: (string | number | boolean | null)[])` - Execute raw SQL with parameters
188+
- `findFirst<K>(table: K, where?: Partial<DT[K]>)` - Find first matching record
189+
- `findMany<K>(table: K, where?: Partial<DT[K]>)` - Find all matching records
190+
- `insert<K>(table: K, data: Partial<DT[K]>)` - Insert new record
191+
- `update<K>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>)` - Update records
192+
- `delete<K>(table: K, where: Partial<DT[K]>)` - Delete records
193+
- `deleteFirst<K>(table: K, where: Partial<DT[K]>)` - Delete first matching record
194+
- `status()` - Get server status and ping (HTTP driver only)
195+
- `close()` - Close database connections
196+
197+
### Return Types
198+
199+
All query methods return a unified result format:
200+
201+
```typescript
202+
type UnifiedQueryResult<T> = {
203+
rows: T[]
204+
rowCount: number
205+
command?: string
206+
fields?: Array<{ name: string; dataTypeID: number }>
207+
}
208+
```
120209
121210
## Development
122211

eslint.config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default unjs({
99
'unicorn/prefer-optional-catch-binding': 'off',
1010
'unicorn/no-null': 'off',
1111
'unicorn/prefer-native-coercion-functions': 'off',
12+
'unicorn/no-empty-files': 'off',
13+
'unicorn/no-array-for-each': 'off',
14+
'unicorn/explicit-length-check': 'off',
1215
},
1316
markdown: {
1417
rules: {

package.json

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
2-
"name": "@lassejlv/postgres-http-driver",
3-
"version": "0.1.0",
4-
"description": "Driver for Postgres HTTP Server (docker.com/lassejlv/postgres_http)",
5-
"repository": "lassejlv/postgres_http",
2+
"name": "driftsql",
3+
"version": "1.0.0",
4+
"author": "lasse vestergaard",
5+
"description": "A lightweight SQL client for TypeScript, supporting multiple databases like PostgreSQL, MySQL, and LibSQL.",
6+
"repository": "lassejlv/driftsql",
67
"license": "MIT",
78
"sideEffects": false,
89
"type": "module",
@@ -39,8 +40,14 @@
3940
},
4041
"packageManager": "[email protected]",
4142
"dependencies": {
43+
"@libsql/client": "^0.15.9",
44+
"@neondatabase/serverless": "^1.0.1",
4245
"@types/pg": "^8.15.4",
46+
"consola": "^3.4.2",
47+
"driftsql": "^0.0.1",
48+
"drizzle-orm": "^0.44.2",
4349
"ky": "^1.8.1",
44-
"pg": "^8.16.0"
50+
"pg": "^8.16.0",
51+
"postgres": "^3.4.7"
4552
}
4653
}

0 commit comments

Comments
 (0)