driftsql 1.0.11 → 1.0.13

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 CHANGED
@@ -1,187 +1,272 @@
1
1
  # DriftSQL
2
2
 
3
- <!-- automd:badges color=yellow -->
4
-
5
3
  [![npm version](https://img.shields.io/npm/v/driftsql?color=yellow)](https://npmjs.com/package/driftsql)
6
4
  [![npm downloads](https://img.shields.io/npm/dm/driftsql?color=yellow)](https://npm.chart.dev/driftsql)
7
5
 
8
- <!-- /automd -->
9
-
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.
6
+ A lightweight, type-safe SQL client for TypeScript that supports multiple database drivers. Import only what you need.
11
7
 
12
8
  ## Features
13
9
 
14
- - 🔐 Type-safe database operations with TypeScript generics
15
- - 🛡️ SQL injection protection with parameterized queries
16
- - 🚀 Multiple driver support (PostgreSQL, LibSQL, HTTP)
17
- - 📝 Auto-completion support for database schema types
18
- - ⚡ Built-in error handling and connection management
19
- - 🔄 Unified API across different database types
10
+ - 🔐 **Type-safe** - Full TypeScript support with generics
11
+ - 🚀 **Modular** - Import only the drivers you need
12
+ - 🛡️ **SQL injection protection** - Parameterized queries by default
13
+ - 🔄 **Unified API** - Same interface across all drivers
14
+ - ⚡ **Multiple drivers** - PostgreSQL, LibSQL, MySQL, SQLite
15
+ - 🎯 **Custom drivers** - Easy to implement your own drivers
20
16
 
21
- ## Supported Drivers
17
+ ## Installation
22
18
 
23
- - **PostgreSQL** - Native PostgreSQL driver via `pg`
24
- - **LibSQL** - SQLite-compatible databases via `@libsql/client`
25
- - **HTTP** - HTTP-based database services
19
+ ```sh
20
+ npm install driftsql
21
+ ```
26
22
 
27
- ## Usage
23
+ ## Basic Usage
28
24
 
29
- Install the package:
25
+ ### Import Individual Drivers
30
26
 
31
- ```sh
32
- # Auto-detect (supports npm, yarn, pnpm, deno and bun)
33
- npx nypm install driftsql
34
- ```
27
+ ```typescript
28
+ import { PostgresDriver, LibSQLDriver, MySQLDriver, SqliteDriver, SQLClient } from 'driftsql'
35
29
 
36
- Import and use:
30
+ // Use PostgreSQL
31
+ const postgresDriver = new PostgresDriver({
32
+ connectionString: 'postgresql://user:password@localhost:5432/mydb'
33
+ })
37
34
 
38
- <!-- automd:jsimport cdn name="driftsql" -->
35
+ // Use LibSQL/Turso
36
+ const libsqlDriver = new LibSQLDriver({
37
+ url: 'libsql://your-database.turso.io',
38
+ authToken: 'your-auth-token'
39
+ })
39
40
 
40
- **ESM** (Node.js, Bun, Deno)
41
+ // Use MySQL
42
+ const mysqlDriver = new MySQLDriver({
43
+ connectionString: 'mysql://user:password@localhost:3306/mydb'
44
+ })
41
45
 
42
- ```js
43
- import { DriftSQLClient } from 'driftsql'
46
+ // Use SQLite
47
+ const sqliteDriver = new SqliteDriver({
48
+ filename: './database.db'
49
+ })
50
+
51
+ // Create a client with any driver
52
+ const client = new SQLClient({ driver: postgresDriver })
44
53
  ```
45
54
 
46
- <!-- /automd -->
55
+ ### Factory Functions
47
56
 
48
- ## Quick Start
57
+ ```typescript
58
+ import { createPostgresClient, createLibSQLClient, createMySQLClient, createSqliteClient } from 'driftsql'
49
59
 
50
- ### Define Your Database Schema
60
+ // Quick setup
61
+ const postgresClient = createPostgresClient({
62
+ connectionString: 'postgresql://user:password@localhost:5432/mydb'
63
+ })
51
64
 
52
- ```typescript
53
- import { DriftSQLClient } from 'driftsql'
65
+ const libsqlClient = createLibSQLClient({
66
+ url: 'file:local.db'
67
+ })
68
+
69
+ const mysqlClient = createMySQLClient({
70
+ connectionString: 'mysql://user:password@localhost:3306/mydb'
71
+ })
54
72
 
55
- // Define your database schema types
73
+ const sqliteClient = createSqliteClient({
74
+ filename: './database.db'
75
+ })
76
+ ```
77
+
78
+ ## Database Operations
79
+
80
+ ### Raw Queries
81
+
82
+ ```typescript
83
+ // Type-safe queries
56
84
  interface User {
57
85
  id: number
58
86
  name: string
59
87
  email: string
60
- created_at: string
61
88
  }
62
89
 
63
- interface Post {
64
- id: number
65
- title: string
66
- content: string | null
67
- user_id: number | null
68
- published: boolean
69
- created_at: Date
70
- updated_at: Date
71
- }
90
+ const result = await client.query<User>('SELECT * FROM users WHERE id = $1', [1])
91
+ console.log(result.rows) // User[]
92
+ console.log(result.rowCount) // number
93
+ ```
94
+
95
+ ### Helper Methods
72
96
 
97
+ ```typescript
73
98
  // Define your database schema
74
99
  interface MyDatabase {
75
100
  users: User
76
101
  posts: Post
77
102
  }
103
+
104
+ const client = new SQLClient<MyDatabase>({ driver: postgresDriver })
105
+
106
+ // Find operations
107
+ const user = await client.findFirst('users', { email: 'user@example.com' })
108
+ const users = await client.findMany('users', {
109
+ where: { active: true },
110
+ limit: 10
111
+ })
112
+
113
+ // Insert
114
+ const newUser = await client.insert('users', {
115
+ name: 'John Doe',
116
+ email: 'john@example.com'
117
+ })
118
+
119
+ // Update
120
+ const updatedUser = await client.update('users',
121
+ { name: 'Jane Doe' },
122
+ { id: 1 }
123
+ )
124
+
125
+ // Delete
126
+ const deletedCount = await client.delete('users', { id: 1 })
127
+ ```
128
+
129
+ ## Transactions
130
+
131
+ ```typescript
132
+ // Check if driver supports transactions
133
+ if (client.supportsTransactions()) {
134
+ await client.transaction(async (txClient) => {
135
+ await txClient.insert('users', { name: 'User 1', email: 'user1@example.com' })
136
+ await txClient.insert('users', { name: 'User 2', email: 'user2@example.com' })
137
+ // Both inserts will be committed together
138
+ })
139
+ }
78
140
  ```
79
141
 
80
- ### Initialize with PostgreSQL
142
+ ## Custom Drivers
143
+
144
+ Implement your own database driver:
81
145
 
82
146
  ```typescript
83
- const db = new DriftSQLClient<MyDatabase>({
84
- drivers: {
85
- postgres: {
86
- connectionString: 'postgresql://user:password@localhost:5432/mydb',
87
- // or individual options:
88
- // host: 'localhost',
89
- // port: 5432,
90
- // database: 'mydb',
91
- // user: 'user',
92
- // password: 'password'
93
- },
94
- },
95
- })
147
+ import type { DatabaseDriver, QueryResult } from 'driftsql'
148
+
149
+ class MyCustomDriver implements DatabaseDriver {
150
+ async query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>> {
151
+ // Your implementation here
152
+ return {
153
+ rows: [], // T[]
154
+ rowCount: 0,
155
+ command: 'SELECT'
156
+ }
157
+ }
158
+
159
+ async close(): Promise<void> {
160
+ // Cleanup logic
161
+ }
162
+ }
163
+
164
+ // Use your custom driver
165
+ const client = new SQLClient({ driver: new MyCustomDriver() })
96
166
  ```
97
167
 
98
- ### Initialize with LibSQL
168
+ ## Driver-Specific Features
169
+
170
+ ### PostgreSQL HTTP Support
99
171
 
100
172
  ```typescript
101
- const db = new DriftSQLClient<MyDatabase>({
102
- drivers: {
103
- libsql: {
104
- url: 'file:local.db',
105
- // or for remote:
106
- // url: 'libsql://your-database.turso.io',
107
- // authToken: 'your-auth-token'
108
- },
109
- },
173
+ const postgresDriver = new PostgresDriver({
174
+ experimental: {
175
+ http: {
176
+ url: 'https://your-postgres-http-api.com',
177
+ apiKey: 'your-api-key'
178
+ }
179
+ }
110
180
  })
111
181
  ```
112
182
 
113
- ### Initialize with HTTP
183
+ ### LibSQL with Turso Serverless
114
184
 
115
185
  ```typescript
116
- const db = new DriftSQLClient<MyDatabase>({
117
- url: 'https://your-database-api.com',
118
- password: 'your-bearer-token',
119
- options: {
120
- defaultTimeout: 5000, // optional, defaults to 5000ms
121
- },
186
+ const libsqlDriver = new LibSQLDriver({
187
+ url: 'libsql://your-database.turso.io',
188
+ authToken: 'your-auth-token',
189
+ useTursoServerlessDriver: true
122
190
  })
123
191
  ```
124
192
 
125
- ### Database Operations
193
+ ### SQLite with Prepared Statements
126
194
 
127
195
  ```typescript
128
- // Raw SQL queries
129
- const users = await db.query<User>('SELECT * FROM users WHERE active = $1', [true])
130
- console.log(users.rows)
196
+ const sqliteDriver = new SqliteDriver({ filename: './db.sqlite' })
197
+ const client = new SQLClient({ driver: sqliteDriver })
131
198
 
132
- // Find operations
133
- const user = await db.findFirst('users', { email: 'user@example.com' })
134
- const activeUsers = await db.findMany('users', { active: true })
199
+ if (client.supportsPreparedStatements()) {
200
+ const stmt = await client.prepare('SELECT * FROM users WHERE id = ?')
201
+ const result = await stmt.execute([1])
202
+ await stmt.finalize()
203
+ }
204
+ ```
135
205
 
136
- // Insert operations
137
- const newUser = await db.insert('users', {
138
- name: 'John Doe',
139
- email: 'john@example.com',
140
- })
206
+ ## Error Handling
141
207
 
142
- // Update operations
143
- const updatedUser = await db.update('users', { name: 'Jane Doe' }, { id: 1 })
208
+ ```typescript
209
+ import { DatabaseError, QueryError, ConnectionError } from 'driftsql'
210
+
211
+ try {
212
+ await client.query('SELECT * FROM users')
213
+ } catch (error) {
214
+ if (error instanceof QueryError) {
215
+ console.log('Query failed:', error.message)
216
+ console.log('Driver:', error.driverType)
217
+ } else if (error instanceof ConnectionError) {
218
+ console.log('Connection failed:', error.message)
219
+ }
220
+ }
221
+ ```
144
222
 
145
- // Delete operations
146
- const deleted = await db.delete('users', { id: 1 })
223
+ ## Fallback Drivers
147
224
 
148
- // Check server status (HTTP only)
149
- const status = await db.status()
150
- console.log(`Database OK: ${status.ok}, Ping: ${status.ping}ms`)
225
+ ```typescript
226
+ // Use multiple drivers with automatic fallback
227
+ const client = new SQLClient({
228
+ driver: primaryDriver,
229
+ fallbackDrivers: [backupDriver1, backupDriver2]
230
+ })
151
231
 
152
- // Clean up connections
153
- await db.close()
232
+ // Will try drivers in order until one succeeds
233
+ const result = await client.query('SELECT 1')
154
234
  ```
155
235
 
156
- ### Constructor Options
236
+ ## API Reference
237
+
238
+ ### DatabaseDriver Interface
157
239
 
158
240
  ```typescript
159
- interface ClientOptions {
160
- url?: string // HTTP server URL (for HTTP driver)
161
- password?: string // Bearer token for HTTP authentication
162
- drivers?: {
163
- libsql?: LibsqlClientConfig // LibSQL configuration
164
- postgres?: PoolConfig // PostgreSQL configuration
165
- postgresNeonHTTP?: {
166
- // Neon configuration (experimental)
167
- connectionString: string
168
- }
169
- }
170
- options?: {
171
- defaultTimeout?: number // Request timeout in milliseconds
172
- }
241
+ interface DatabaseDriver {
242
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>
243
+ close(): Promise<void>
173
244
  }
174
245
  ```
175
246
 
176
- </details>
247
+ ### SQLClient
177
248
 
178
- ## License
249
+ ```typescript
250
+ class SQLClient<DT = any> {
251
+ constructor(options: { driver: DatabaseDriver; fallbackDrivers?: DatabaseDriver[] })
252
+
253
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>
254
+ findFirst<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K] | null>
255
+ findMany<K extends keyof DT>(table: K, options?: FindManyOptions<DT[K]>): Promise<DT[K][]>
256
+ insert<K extends keyof DT>(table: K, data: Partial<DT[K]>): Promise<DT[K]>
257
+ update<K extends keyof DT>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>): Promise<DT[K] | null>
258
+ delete<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<number>
259
+
260
+ transaction<T>(callback: (client: SQLClient<DT>) => Promise<T>): Promise<T>
261
+ prepare(sql: string): Promise<PreparedStatement>
262
+
263
+ getDriver(): DatabaseDriver
264
+ supportsTransactions(): boolean
265
+ supportsPreparedStatements(): boolean
266
+ close(): Promise<void>
267
+ }
268
+ ```
179
269
 
180
- <!-- automd:contributors license=MIT -->
270
+ ## License
181
271
 
182
- Published under the [MIT](https://github.com/lassejlv/driftsql/blob/main/LICENSE) license.
183
- Made by [community](https://github.com/lassejlv/driftsql/graphs/contributors) 💛
184
- <br><br>
185
- <a href="https://github.com/lassejlv/driftsql/graphs/contributors">
186
- <img src="https://contrib.rocks/image?repo=lassejlv/driftsql" />
187
- </a>
272
+ Published under the [MIT](https://github.com/lassejlv/driftsql/blob/main/LICENSE) license.
package/dist/index.d.mts CHANGED
@@ -1,59 +1,133 @@
1
+ interface QueryResult<T = any> {
2
+ rows: T[];
3
+ rowCount: number;
4
+ command?: string;
5
+ fields?: QueryField[];
6
+ }
7
+ interface QueryField {
8
+ name: string;
9
+ dataTypeID: number;
10
+ }
11
+ interface DatabaseDriver {
12
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
13
+ close(): Promise<void>;
14
+ }
15
+ interface TransactionCapable {
16
+ transaction<T>(callback: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
17
+ }
18
+ interface PreparedStatementCapable {
19
+ prepare(sql: string): Promise<PreparedStatement>;
20
+ }
21
+ interface PreparedStatement {
22
+ execute<T = any>(params?: any[]): Promise<QueryResult<T>>;
23
+ finalize(): Promise<void>;
24
+ }
25
+
1
26
  interface PostgresConfig {
2
- connectionString: string;
27
+ connectionString?: string;
28
+ experimental?: {
29
+ http?: {
30
+ url: string;
31
+ apiKey?: string;
32
+ };
33
+ };
34
+ }
35
+ declare class PostgresDriver implements DatabaseDriver, TransactionCapable {
36
+ private client;
37
+ constructor(config: PostgresConfig);
38
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
39
+ transaction<T>(callback: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
40
+ close(): Promise<void>;
3
41
  }
4
42
 
5
43
  interface LibSQLConfig {
6
44
  url: string;
7
45
  authToken?: string;
8
- options?: {
9
- experimental?: {
10
- useTursoServerlessDriver?: boolean;
11
- };
12
- };
46
+ useTursoServerlessDriver?: boolean;
47
+ }
48
+ declare class LibSQLDriver implements DatabaseDriver, TransactionCapable {
49
+ private client;
50
+ constructor(config: LibSQLConfig);
51
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
52
+ transaction<T>(callback: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
53
+ close(): Promise<void>;
54
+ private convertLibsqlResult;
13
55
  }
14
56
 
15
57
  interface MySQLConfig {
16
58
  connectionString: string;
17
59
  }
60
+ declare class MySQLDriver implements DatabaseDriver, TransactionCapable {
61
+ private client;
62
+ constructor(config: MySQLConfig);
63
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
64
+ transaction<T>(callback: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
65
+ close(): Promise<void>;
66
+ }
18
67
 
19
- type Drivers = ClientOptions['drivers'];
20
- declare const inspectDB: (drivers: Drivers) => Promise<never>;
68
+ interface SqliteConfig {
69
+ filename: string;
70
+ readonly?: boolean;
71
+ }
72
+ declare class SqliteDriver implements DatabaseDriver, TransactionCapable, PreparedStatementCapable {
73
+ private client;
74
+ constructor(config: SqliteConfig);
75
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
76
+ transaction<T>(callback: (driver: DatabaseDriver) => Promise<T>): Promise<T>;
77
+ prepare(sql: string): Promise<PreparedStatement>;
78
+ close(): Promise<void>;
79
+ exec(sql: string): void;
80
+ backup(filename: string): Promise<void>;
81
+ pragma(pragma: string): any;
82
+ }
21
83
 
22
- type UnifiedQueryResult<T extends Record<string, any>> = {
23
- rows: T[];
24
- rowCount: number;
25
- command?: string;
26
- fields?: Array<{
27
- name: string;
28
- dataTypeID: number;
29
- }>;
30
- };
31
- interface ClientOptions {
32
- drivers: {
33
- libsql?: LibSQLConfig;
34
- postgres?: PostgresConfig;
35
- mysql?: MySQLConfig;
36
- };
84
+ interface ClientOptions<T extends DatabaseDriver = DatabaseDriver> {
85
+ driver: T;
86
+ fallbackDrivers?: DatabaseDriver[];
37
87
  }
38
- declare class DriftSQLClient<DT> {
39
- private postgres?;
40
- private libsql?;
41
- private mysql?;
42
- private drivers;
88
+ declare class SQLClient<DT = any> {
89
+ private primaryDriver;
90
+ private fallbackDrivers;
43
91
  constructor(options: ClientOptions);
44
- readonly inspect: () => Promise<void>;
45
- query<T extends Record<string, any>>(query: string, args?: (string | number | boolean | null)[]): Promise<UnifiedQueryResult<T>>;
92
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
93
+ transaction<T>(callback: (client: SQLClient<DT>) => Promise<T>): Promise<T>;
94
+ prepare(sql: string): Promise<PreparedStatement>;
46
95
  findFirst<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K] | null>;
47
96
  findMany<K extends keyof DT>(table: K, options?: {
48
97
  where?: Partial<DT[K]>;
49
98
  limit?: number;
99
+ offset?: number;
50
100
  }): Promise<DT[K][]>;
51
101
  insert<K extends keyof DT>(table: K, data: Partial<DT[K]>): Promise<DT[K]>;
52
102
  update<K extends keyof DT>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>): Promise<DT[K] | null>;
53
- delete<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<boolean>;
54
- deleteFirst<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<boolean>;
103
+ delete<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<number>;
104
+ getDriver(): DatabaseDriver;
105
+ supportsTransactions(): boolean;
106
+ supportsPreparedStatements(): boolean;
55
107
  close(): Promise<void>;
56
108
  }
109
+ declare function createPostgresClient<DT = any>(config: {
110
+ connectionString?: string;
111
+ experimental?: {
112
+ http?: {
113
+ url: string;
114
+ apiKey?: string;
115
+ };
116
+ };
117
+ }): SQLClient<DT>;
118
+ declare function createLibSQLClient<DT = any>(config: {
119
+ url: string;
120
+ authToken?: string;
121
+ useTursoServerlessDriver?: boolean;
122
+ }): SQLClient<DT>;
123
+ declare function createMySQLClient<DT = any>(config: {
124
+ connectionString: string;
125
+ }): SQLClient<DT>;
126
+ declare function createSqliteClient<DT = any>(config: {
127
+ filename: string;
128
+ readonly?: boolean;
129
+ }): SQLClient<DT>;
130
+ declare const DriftSQLClient: typeof SQLClient;
57
131
 
58
- export { DriftSQLClient, inspectDB };
59
- export type { ClientOptions, UnifiedQueryResult };
132
+ export { DriftSQLClient, LibSQLDriver, MySQLDriver, PostgresDriver, SQLClient, SqliteDriver, createLibSQLClient, createMySQLClient, createPostgresClient, createSqliteClient };
133
+ export type { ClientOptions, DatabaseDriver, QueryResult };