driftsql 1.0.32 → 2.0.0-beta.2
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 +276 -96
- package/dist/index.d.ts +360 -37
- package/dist/index.js +81 -21
- package/dist/postgres-9C7eE0wB.js +5 -0
- package/dist/postgres-DWtAqXNK.js +1 -0
- package/dist/type-generator-Ba8bgnMm.js +7 -0
- package/dist/type-generator-DbcqBk-4.js +1 -0
- package/package.json +37 -24
- package/.prettierrc +0 -5
- package/dist/drivers/bun.d.ts +0 -22
- package/dist/drivers/libsql.d.ts +0 -23
- package/dist/drivers/mysql.d.ts +0 -20
- package/dist/drivers/neon.d.ts +0 -19
- package/dist/drivers/postgres.d.ts +0 -26
- package/dist/drivers/poubelle/client.d.ts +0 -20
- package/dist/drivers/poubelle/poubelle.d.ts +0 -11
- package/dist/drivers/sqlitecloud.d.ts +0 -21
- package/dist/drivers/surreal.d.ts +0 -17
- package/dist/inspect.d.ts +0 -7
- package/dist/pull.d.ts +0 -7
- package/dist/types.d.ts +0 -49
- package/tsconfig.json +0 -34
package/README.md
CHANGED
|
@@ -1,148 +1,328 @@
|
|
|
1
|
-
# DriftSQL
|
|
1
|
+
# DriftSQL (beta)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://npm.chart.dev/driftsql)
|
|
3
|
+
A modern, type-safe SQL client with built-in schema builder and migration system for TypeScript.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **High-Performance SQL Client** with connection pooling and query caching
|
|
8
|
+
- 🎯 **Type-Safe Schema Builder** similar to Drizzle/Prisma
|
|
9
|
+
- 🔄 **Migration System** with automatic change detection
|
|
10
|
+
- 🛠️ **CLI Tools** for database management
|
|
11
|
+
- 📦 **Multiple Databases** - PostgreSQL, MySQL, SQLite support
|
|
12
|
+
- ⚡ **Helper Functions** for common CRUD operations
|
|
13
|
+
- 🔍 **Database Inspection** to generate TypeScript types
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Install
|
|
19
|
+
bun add driftsql
|
|
7
20
|
|
|
8
|
-
|
|
21
|
+
# Initialize with a basic notes schema
|
|
22
|
+
driftsql init
|
|
9
23
|
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
# Update .env with your DATABASE_URL
|
|
25
|
+
cp .env.example .env
|
|
26
|
+
|
|
27
|
+
# Generate migration from schema
|
|
28
|
+
driftsql migrate:generate initial
|
|
29
|
+
|
|
30
|
+
# Run migrations
|
|
31
|
+
driftsql migrate:up
|
|
32
|
+
|
|
33
|
+
# Edit schema.ts, then generate new migrations automatically
|
|
34
|
+
driftsql migrate:generate add_posts
|
|
12
35
|
```
|
|
13
36
|
|
|
14
|
-
##
|
|
37
|
+
## Automatic Workflow
|
|
15
38
|
|
|
16
|
-
|
|
17
|
-
- 🚀 **Modular** - Import only what you need
|
|
18
|
-
- 🛡️ **SQL injection protection** - Parameterized queries
|
|
19
|
-
- 🔄 **Unified API** - Same interface across all drivers
|
|
20
|
-
- ⚡ **Transactions** - When supported by the driver
|
|
39
|
+
DriftSQL automatically detects schema changes and generates migrations for you!
|
|
21
40
|
|
|
22
|
-
|
|
41
|
+
1. Define your schema in `schema.ts`:
|
|
23
42
|
|
|
24
43
|
```typescript
|
|
25
|
-
import {
|
|
44
|
+
import { createTable, serial, varchar, text } from 'driftsql'
|
|
26
45
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
connectionString: 'postgresql://user:password@localhost:5432/mydb',
|
|
46
|
+
const usersTable = createTable('users', (table) => {
|
|
47
|
+
table.column(serial('id').primaryKey()).column(varchar('email', 255).unique().notNull()).column(varchar('name', 255).notNull())
|
|
30
48
|
})
|
|
31
|
-
const client = new SQLClient({ driver })
|
|
32
49
|
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
const postsTable = createTable('posts', (table) => {
|
|
51
|
+
table.column(serial('id').primaryKey()).column(integer('user_id').references('users', 'id')).column(varchar('title', 255).notNull()).column(text('content'))
|
|
52
|
+
})
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
const user = await client.findFirst('users', { email: 'user@example.com' })
|
|
38
|
-
const newUser = await client.insert('users', { name: 'John', email: 'john@example.com' })
|
|
54
|
+
export default [usersTable.getDefinition(), postsTable.getDefinition()]
|
|
39
55
|
```
|
|
40
56
|
|
|
41
|
-
|
|
57
|
+
2. Generate migration:
|
|
42
58
|
|
|
43
|
-
```
|
|
44
|
-
|
|
59
|
+
```bash
|
|
60
|
+
driftsql migrate:generate
|
|
61
|
+
```
|
|
45
62
|
|
|
46
|
-
|
|
47
|
-
const pg = new PostgresDriver({ connectionString: 'postgresql://...' })
|
|
63
|
+
3. DriftSQL automatically:
|
|
48
64
|
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
- ✅ Compares with the last snapshot
|
|
66
|
+
- ✅ Detects all changes
|
|
67
|
+
- ✅ Generates migration file
|
|
68
|
+
- ✅ Generates TypeScript types (`db-types.ts`)
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
const libsql = new LibSQLDriver({ url: 'libsql://...', authToken: '...' })
|
|
54
|
-
// or for local SQLite: new LibSQLDriver({ url: 'file:./database.db' })
|
|
70
|
+
4. Apply migrations:
|
|
55
71
|
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
```bash
|
|
73
|
+
driftsql migrate:up
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
5. Use type-safe queries:
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
```typescript
|
|
79
|
+
import { Database } from './db-types'
|
|
80
|
+
const client = new SQLClient<Database>({
|
|
81
|
+
/* ... */
|
|
82
|
+
})
|
|
61
83
|
```
|
|
62
84
|
|
|
63
|
-
##
|
|
85
|
+
## Usage
|
|
64
86
|
|
|
65
|
-
|
|
87
|
+
### SQL Client with Type Safety
|
|
66
88
|
|
|
67
|
-
|
|
68
|
-
import type { DatabaseDriver, QueryResult } from 'driftsql'
|
|
69
|
-
|
|
70
|
-
class MyCustomDriver implements DatabaseDriver {
|
|
71
|
-
async query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>> {
|
|
72
|
-
// Your implementation here
|
|
73
|
-
return {
|
|
74
|
-
rows: [], // T[]
|
|
75
|
-
rowCount: 0,
|
|
76
|
-
command: 'SELECT',
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async close(): Promise<void> {
|
|
81
|
-
// Cleanup logic
|
|
82
|
-
}
|
|
83
|
-
}
|
|
89
|
+
TypeScript types are **automatically generated** when you run `migrate:generate`:
|
|
84
90
|
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
```bash
|
|
92
|
+
driftsql migrate:generate # Creates migration AND db-types.ts automatically
|
|
87
93
|
```
|
|
88
94
|
|
|
89
|
-
|
|
95
|
+
Or generate them manually:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
driftsql generate:types --schema ./schema.ts --output ./db-types.ts
|
|
99
|
+
```
|
|
90
100
|
|
|
91
|
-
|
|
101
|
+
Then use them for full type safety:
|
|
92
102
|
|
|
93
103
|
```typescript
|
|
94
|
-
import {
|
|
104
|
+
import { SQLClient, PostgresDriver } from 'driftsql'
|
|
105
|
+
import type { Database } from './db-types'
|
|
95
106
|
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
// Generic parameter makes client type-safe
|
|
108
|
+
const client = new SQLClient<Database>({
|
|
109
|
+
driver: new PostgresDriver({
|
|
110
|
+
connectionString: process.env.DATABASE_URL!,
|
|
111
|
+
max: 10, // Connection pool size
|
|
112
|
+
idle_timeout: 30, // Seconds
|
|
113
|
+
connect_timeout: 10, // Seconds
|
|
114
|
+
}),
|
|
115
|
+
cacheTTL: 5000, // Cache TTL in ms (default: 5000)
|
|
98
116
|
})
|
|
99
117
|
|
|
100
|
-
//
|
|
101
|
-
await
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
// Raw SQL queries (no type safety, but flexible)
|
|
119
|
+
const result = await client.query('SELECT * FROM users WHERE id = $1', [1])
|
|
120
|
+
|
|
121
|
+
// ✅ Type-safe helper methods (TypeScript validates everything!)
|
|
122
|
+
const user = await client.findFirst('users', { email: 'test@example.com' })
|
|
123
|
+
// ^^^^^ TypeScript ensures 'users' exists
|
|
124
|
+
// ^^^^^ TypeScript ensures 'email' is a valid column
|
|
125
|
+
|
|
126
|
+
const activeUsers = await client.findMany('users', {
|
|
127
|
+
where: { active: true }, // ✅ TypeScript validates field names and types
|
|
128
|
+
limit: 10,
|
|
129
|
+
offset: 0,
|
|
104
130
|
})
|
|
105
|
-
```
|
|
106
131
|
|
|
107
|
-
|
|
132
|
+
// ✅ Insert with type checking
|
|
133
|
+
const newUser = await client.insert('users', {
|
|
134
|
+
email: 'new@example.com', // ✅ Must be a string
|
|
135
|
+
name: 'New User', // ✅ Must be a string
|
|
136
|
+
active: true, // ✅ Must be a boolean
|
|
137
|
+
// invalid: 'field' // ❌ TypeScript error!
|
|
138
|
+
})
|
|
108
139
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
140
|
+
// ✅ Update with type checking
|
|
141
|
+
const updated = await client.update(
|
|
142
|
+
'users',
|
|
143
|
+
{ name: 'Updated Name' }, // ✅ Only valid columns
|
|
144
|
+
{ id: 1 } // ✅ Only valid columns in where clause
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
// ✅ Delete with type checking
|
|
148
|
+
const deletedCount = await client.delete('users', { id: 1 })
|
|
149
|
+
|
|
150
|
+
// Transactions - all operations succeed or all fail
|
|
151
|
+
await client.transaction(async (tx) => {
|
|
152
|
+
const user = await tx.insert('users', { email: 'user@example.com', name: 'User' })
|
|
153
|
+
await tx.insert('posts', { user_id: user.id, title: 'First Post' })
|
|
154
|
+
await tx.query('UPDATE users SET post_count = post_count + 1 WHERE id = $1', [user.id])
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Cache management
|
|
158
|
+
const stats = client.getCacheStats() // { size: 5, ttl: 5000 }
|
|
159
|
+
client.clearCache() // Clear all cached queries
|
|
118
160
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
published: boolean
|
|
161
|
+
// Check driver capabilities
|
|
162
|
+
if (client.supportsTransactions()) {
|
|
163
|
+
await client.transaction(async (tx) => {
|
|
164
|
+
/* ... */
|
|
165
|
+
})
|
|
125
166
|
}
|
|
126
167
|
|
|
127
|
-
|
|
128
|
-
users
|
|
129
|
-
|
|
168
|
+
if (client.supportsPreparedStatements()) {
|
|
169
|
+
const stmt = await client.prepare('SELECT * FROM users WHERE id = $1')
|
|
170
|
+
const result = await stmt.execute([1])
|
|
171
|
+
await stmt.finalize()
|
|
130
172
|
}
|
|
173
|
+
|
|
174
|
+
await client.close()
|
|
131
175
|
```
|
|
132
176
|
|
|
133
|
-
|
|
177
|
+
### Schema Builder
|
|
134
178
|
|
|
135
179
|
```typescript
|
|
136
|
-
import
|
|
137
|
-
|
|
180
|
+
import { createTable, createMigration, serial, varchar, text, timestamp } from 'driftsql'
|
|
181
|
+
|
|
182
|
+
// Define table
|
|
183
|
+
const usersTable = createTable('users', (table) => {
|
|
184
|
+
table
|
|
185
|
+
.column(serial('id').primaryKey())
|
|
186
|
+
.column(varchar('email', 255).unique().notNull())
|
|
187
|
+
.column(varchar('name', 255).notNull())
|
|
188
|
+
.column(text('bio'))
|
|
189
|
+
.column(timestamp('created_at').default('CURRENT_TIMESTAMP').notNull())
|
|
190
|
+
.index('idx_users_email', ['email'])
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
// Create migration
|
|
194
|
+
const migration = createMigration('postgres').createTable(usersTable).build('001', 'create_users_table')
|
|
195
|
+
|
|
196
|
+
// View generated SQL
|
|
197
|
+
console.log(migration.up) // CREATE TABLE statements
|
|
198
|
+
console.log(migration.down) // DROP TABLE statements
|
|
199
|
+
```
|
|
138
200
|
|
|
139
|
-
|
|
201
|
+
### Change Detection
|
|
140
202
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
203
|
+
```typescript
|
|
204
|
+
import { detectChanges, generateMigrationFromChanges } from 'driftsql'
|
|
205
|
+
|
|
206
|
+
const oldSchema = [
|
|
207
|
+
/* previous table definitions */
|
|
208
|
+
]
|
|
209
|
+
const newSchema = [
|
|
210
|
+
/* updated table definitions */
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
// Detect what changed
|
|
214
|
+
const changes = detectChanges(oldSchema, newSchema, 'postgres')
|
|
215
|
+
|
|
216
|
+
// Generate migration from changes
|
|
217
|
+
const migration = generateMigrationFromChanges(changes, '002', 'auto_migration')
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### CLI Commands
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Initialize project
|
|
224
|
+
driftsql init
|
|
225
|
+
|
|
226
|
+
# Create new migration
|
|
227
|
+
driftsql migrate:create add_users_table
|
|
228
|
+
|
|
229
|
+
# Run migrations
|
|
230
|
+
driftsql migrate:up
|
|
231
|
+
|
|
232
|
+
# Check migration status
|
|
233
|
+
driftsql migrate:status
|
|
234
|
+
|
|
235
|
+
# Rollback last migration
|
|
236
|
+
driftsql migrate:down
|
|
237
|
+
|
|
238
|
+
# Reset all migrations
|
|
239
|
+
driftsql migrate:reset
|
|
240
|
+
|
|
241
|
+
# Generate TypeScript types from database
|
|
242
|
+
driftsql db:inspect --output ./src/db-types.ts
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Performance Features
|
|
246
|
+
|
|
247
|
+
- **Connection Pooling**: Configurable pool size and timeouts
|
|
248
|
+
- **Query Caching**: Built-in LRU cache with TTL (default 5 seconds)
|
|
249
|
+
- **Smart Fallbacks**: Fast-path primary driver with automatic fallback support
|
|
250
|
+
- **Optimized Error Handling**: Reduced overhead in CRUD operations
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const client = new SQLClient({
|
|
254
|
+
driver: new PostgresDriver({
|
|
255
|
+
connectionString: process.env.DATABASE_URL!,
|
|
256
|
+
max: 10, // Pool size
|
|
257
|
+
idle_timeout: 30, // Seconds
|
|
258
|
+
connect_timeout: 10, // Seconds
|
|
259
|
+
}),
|
|
260
|
+
cacheTTL: 5000, // Cache TTL in ms
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
// Cache management
|
|
264
|
+
client.clearCache()
|
|
265
|
+
const stats = client.getCacheStats()
|
|
144
266
|
```
|
|
145
267
|
|
|
268
|
+
## Supported Databases
|
|
269
|
+
|
|
270
|
+
- ✅ **PostgreSQL** - Full feature support
|
|
271
|
+
- ✅ **MySQL** - Full feature support
|
|
272
|
+
- ✅ **SQLite** - Full feature support
|
|
273
|
+
- 🔄 More coming soon...
|
|
274
|
+
|
|
275
|
+
## Column Types
|
|
276
|
+
|
|
277
|
+
**Numeric**: `serial`, `bigserial`, `integer`, `bigint`, `smallint`, `decimal`, `numeric`, `real`, `doublePrecision`
|
|
278
|
+
|
|
279
|
+
**String**: `text`, `varchar`, `char`
|
|
280
|
+
|
|
281
|
+
**Date/Time**: `timestamp`, `timestamptz`, `date`, `time`
|
|
282
|
+
|
|
283
|
+
**Other**: `boolean`, `json`, `jsonb`, `uuid`, `bytea`
|
|
284
|
+
|
|
285
|
+
## Column Modifiers
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
column.primaryKey().notNull().unique().default(value).length(255).precision(10, 2).references('users', 'id').onDelete('CASCADE').check('age >= 18')
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Documentation
|
|
292
|
+
|
|
293
|
+
- [Schema Builder Guide](./SCHEMA.md) - Complete schema builder documentation
|
|
294
|
+
- [CLI Reference](./CLI.md) - All CLI commands and usage
|
|
295
|
+
|
|
296
|
+
## Examples
|
|
297
|
+
|
|
298
|
+
Check the `examples/` directory for:
|
|
299
|
+
|
|
300
|
+
- Basic schema creation
|
|
301
|
+
- Migration generation
|
|
302
|
+
- Change detection
|
|
303
|
+
- Multiple database dialects
|
|
304
|
+
|
|
305
|
+
## Contributing
|
|
306
|
+
|
|
307
|
+
Contributions are welcome! Please read our contributing guidelines.
|
|
308
|
+
|
|
146
309
|
## License
|
|
147
310
|
|
|
148
|
-
|
|
311
|
+
MIT
|
|
312
|
+
|
|
313
|
+
## Roadmap
|
|
314
|
+
|
|
315
|
+
- [x] PostgreSQL driver with helpers
|
|
316
|
+
- [x] Query caching
|
|
317
|
+
- [x] Schema builder
|
|
318
|
+
- [x] Migration system
|
|
319
|
+
- [x] Change detection
|
|
320
|
+
- [x] CLI tools
|
|
321
|
+
- [x] MySQL helpers
|
|
322
|
+
- [x] SQLite helpers
|
|
323
|
+
- [ ] MySQL driver implementation
|
|
324
|
+
- [ ] SQLite driver implementation
|
|
325
|
+
- [ ] More database drivers (SQL Server, Oracle, etc.)
|
|
326
|
+
- [ ] Schema diffing from live database
|
|
327
|
+
- [ ] Migration squashing
|
|
328
|
+
- [ ] Seeding system
|